Czy jest jakiś sposób, aby ustawić to dla wszystkich poleceń w funkcji / skrypcie bash?
Alexander Mills,
Odpowiedzi:
39
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; }
To faktycznie zmniejsza liczbę procesów tylko o jeden. (Ale może być szybsze, ponieważ nie są używane sedawk
wyrażenia
BTW, byłem ciekawy wydajności i oto wyniki mojego prostego testu porównawczego przy użyciu bash, sed i awk. Wepchnięcie około 1000 wierszy tekstu (wyjście dmesg) do pliku FIFO, a następnie czytanie ich w ten sposób: pastebin.ca/1606844 Wygląda na to, że awk jest zwycięzcą. Jakieś pomysły, dlaczego?
Ilya Zakreuski
1
bądź ostrożny, przeprowadzając takie testy czasowe - spróbuj uruchomić je we wszystkich 6 różnych zamówieniach, a następnie uśrednij wyniki. Różne zamówienia w celu złagodzenia efektów pamięci podręcznej bloków i średnie w celu złagodzenia efektów przerwania / planowania w tle.
pjz
To pytanie jest oznaczone jako „shell”, a nie „bash”.
fiatjaf
1
Łatwo jest też zawinąć go w funkcję:function prepend() { while read line; do echo "${1}${line}"; done; }
Możesz po prostu wyjść z zakresu cytatów, aby wyłuskać zmienną: cmd | awk '{print "['$V]' " $0}'- należy to ocenić raz na początku, aby nie narzucać wydajności.
Robert
13
Z całym uznaniem dla @grawity przesyłam jego komentarz jako odpowiedź, ponieważ wydaje mi się to najlepszą odpowiedzią tutaj.
Przypuszczam, że to zależy od twojego celu. Jeśli Twoim celem jest po prostu wstawianie do każdej linii w pliku, osiąga ten cel przy użyciu bardzo niewielu znaków, przy użyciu bardzo znanego narzędzia. Zdecydowanie wolę to od 10-wierszowego skryptu bash. 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.
Eric Wilson,
Odpowiedź przesłana przez pjz jest również niezłą linią. Nie powoduje dodatkowych programów, procesów i może działać nieco szybciej.
user14645
3
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.
Tino
Miły. To polecenie jest łatwo aliasowane. 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.
W ogólnym przypadku 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.
W bardzo szczególnych sytuacjach, w których dominują widelce, uruchomienie skryptu jako skompilowanego 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.
Tworzenie statycznie powiązanego pliku binarnego do pokonania 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):
Wypróbowałem to podejście, ale z tymi >(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
Odpowiedzi:
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:
pozwoli na użycie go w następujący sposób:
źródło
sed
awk
function prepend() { while read line; do echo "${1}${line}"; done; }
Spróbuj tego:
Twoje zdrowie
źródło
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.
źródło
awk
Jedna wkładka jest dość miłe, ale myślę, że więcej ludzi znased
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
czytacmd
i nie wykonuje tego. Albocmd | sed 's/^/[ERROR] /'
albosed 's/^/[ERROR] /' <(cmd)
albocmd > >(sed 's/^/[ERROR] /')
. Ale uwaga ta ostatnia. Mimo, że ta pozwala na dostęp do wartości zwracanejcmd
przezsed
działa w tle, więc jest prawdopodobne, widać wyjście po cmd gotowych. Dobry do logowania się do pliku. I zauważ, żeawk
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łoalias
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 iperl
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 tegobash
jest dość powolny w porównaniu ze skompilowanymiksh
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:
Dwa binarne warianty jednego z moich narzędzi (jednak nie jest zoptymalizowane pod kątem szybkości):
Buforowane w Pythonie:
Python niebuforowany:
źródło
awk -v T="[TEST %Y%m%d-%H%M%S] " '{ print strftime(T) $0 }'
wypisać znacznik czasuźródło
sed 's/^/[ERROR] /'
Chciałem rozwiązania, które obsługiwałoby stdout i stderr, więc napisałem
prepend.sh
i postawiłem na swojej drodze:Teraz mogę po prostu uruchomić
prepend.sh "[ERROR]" cmd ...
, aby dodać „[ERROR]” do wyjściacmd
i nadal mieć osobne stderr i stdout.źródło
>(
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