Szukasz czegoś takiego? Jakieś pomysły?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Szukasz czegoś takiego? Jakieś pomysły?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Odpowiedzi:
cmd | while read line; do echo "[ERROR] $line"; done
ma tę zaletę, że wykorzystuje tylko wbudowane bash, więc mniej procesów zostanie utworzonych / zniszczonych, więc powinno być odrobinę szybsze niż awk lub sed.
@tzrik wskazuje, że może to również być przyjemna funkcja bash. Definiując to tak:
function prepend() { while read line; do echo "${1}${line}"; done; }
pozwoli na użycie go w następujący sposób:
cmd | prepend "[ERROR] "
sedawk
function prepend() { while read line; do echo "${1}${line}"; done; }
Spróbuj tego:
cmd | awk '{print "[ERROR] " $0}'
Twoje zdrowie
awk -vT="[ERROR] " '{ print T $0 }'lubawk -vT="[ERROR]" '{ print T " " $0 }'
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'lubT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
cmd | awk '{print "['$V]' " $0}'- należy to ocenić raz na początku, aby nie narzucać wydajności.
Z całym uznaniem dla @grawity przesyłam jego komentarz jako odpowiedź, ponieważ wydaje mi się to najlepszą odpowiedzią tutaj.
sed 's/^/[ERROR] /' cmd
awkJedna wkładka jest dość miłe, ale myślę, że więcej ludzi zna sedniż awk. Skrypt bash jest dobry do tego, co robi, ale wydaje się, że odpowiada na pytanie, które nie zostało zadane.
sed X cmdczyta cmdi nie wykonuje tego. Albo cmd | sed 's/^/[ERROR] /'albo sed 's/^/[ERROR] /' <(cmd)albo cmd > >(sed 's/^/[ERROR] /'). Ale uwaga ta ostatnia. Mimo, że ta pozwala na dostęp do wartości zwracanej cmdprzez seddziała w tle, więc jest prawdopodobne, widać wyjście po cmd gotowych. Dobry do logowania się do pliku. I zauważ, że awkprawdopodobnie jest szybszy niż sed.
alias lpad="sed 's/^/ /'". zamiast BŁĘDU wstawiam 4 wiodące spacje. Teraz, dla magicznej sztuczki: ls | lpad | pbcopyprzygotuje wyjście ls z 4 spacjami, co oznacza go jako Markdown dla kodu , co oznacza, że wklejasz schowek ( pbcopy chwyta go, na Macach) bezpośrednio w StackOverflow lub w innym kontekście Markdown . Nie udało aliassię odpowiedzieć na awk (za pierwszym razem), więc ten wygrywa. Podczas odczytu rozwiązaniem jest również alias-stanie, ale uważam ten sed bardziej wyraziste.
Utworzyłem repozytorium GitHub, aby przeprowadzić testy prędkości.
Wynik to:
awkjest najszybszy. sedjest nieco wolniejszy i perlnie jest dużo wolniejszy niż sed. Najwyraźniej wszystkie te są wysoce zoptymalizowanymi językami do przetwarzania tekstu.kshskryptu ( shcomp) może zaoszczędzić jeszcze więcej czasu przetwarzania. W przeciwieństwie do tego bashjest dość powolny w porównaniu ze skompilowanymi kshskryptami.awknie wydaje się warte wysiłku.W przeciwieństwie do tego pythonjest bardzo powolny, ale nie testowałem skompilowanej skrzynki, ponieważ zwykle nie jest to, co zrobiłbyś w takiej skrzynce.
Testowane są następujące warianty:
while read line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST]" $line; done
while read -r line; do echo "[TEST]" "$line"; done
sed 's/^/[TEST] /'
awk '{ print "[TEST] " $0 }'
awk -vT="[TEST] " '{ print T $0 }'
awk -vT="[TEST]" '{ print T " " $0 }'
awk -vT="[TEST]" 'BEGIN { T=T " "; } { print T $0 }'
T="[TEST] " awk '{ print ENVIRON["T"] $0 }'
T="[TEST]" awk '{ print ENVIRON["T"] " " $0 }'
T="[TEST]" awk 'BEGIN { T=ENVIRON["T"] " " } { print T $0 }'
perl -ne 'print "[TEST] $_"'
Dwa binarne warianty jednego z moich narzędzi (jednak nie jest zoptymalizowane pod kątem szybkości):
./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''
Buforowane w Pythonie:
python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'
Python niebuforowany:
python -uSc 'import sys
while 1:
line = sys.stdin.readline()
if not line: break
print "[TEST]",line,'
awk -v T="[TEST %Y%m%d-%H%M%S] " '{ print strftime(T) $0 }'wypisać znacznik czasu
Chciałem rozwiązania, które obsługiwałoby stdout i stderr, więc napisałem prepend.shi postawiłem na swojej drodze:
#!/bin/bash
prepend_lines(){
local prepended=$1
while read line; do
echo "$prepended" "$line"
done
}
tag=$1
shift
"$@" > >(prepend_lines "$tag") 2> >(prepend_lines "$tag" 1>&2)
Teraz mogę po prostu uruchomić prepend.sh "[ERROR]" cmd ..., aby dodać „[ERROR]” do wyjścia cmdi nadal mieć osobne stderr i stdout.
>(powłokami wewnętrznymi działo się coś , czego nie mogłem całkowicie rozwiązać. Wydawało się, że skrypt się kończy, a dane wyjściowe docierają do terminala po powrocie monitu, co było nieco nieuporządkowane. W końcu znalazłem odpowiedź tutaj stackoverflow.com/a/25948606/409638