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] "
sed
awk
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
awk
Jedna wkładka jest dość miłe, ale myślę, że więcej ludzi zna sed
niż awk
. Skrypt bash jest dobry do tego, co robi, ale wydaje się, że odpowiada na pytanie, które nie zostało zadane.
sed X cmd
czyta cmd
i 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 cmd
przez sed
działa w tle, więc jest prawdopodobne, widać wyjście po cmd gotowych. Dobry do logowania się do pliku. I zauważ, że awk
prawdopodobnie jest szybszy niż sed
.
alias lpad="sed 's/^/ /'"
. zamiast BŁĘDU wstawiam 4 wiodące spacje. Teraz, dla magicznej sztuczki: ls | lpad | pbcopy
przygotuje 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 alias
się 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:
awk
jest najszybszy. sed
jest nieco wolniejszy i perl
nie jest dużo wolniejszy niż sed
. Najwyraźniej wszystkie te są wysoce zoptymalizowanymi językami do przetwarzania tekstu.ksh
skryptu ( shcomp
) może zaoszczędzić jeszcze więcej czasu przetwarzania. W przeciwieństwie do tego bash
jest dość powolny w porównaniu ze skompilowanymi ksh
skryptami.awk
nie wydaje się warte wysiłku.W przeciwieństwie do tego python
jest 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.sh
i 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 cmd
i 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