Odpowiedzi:
Jednym z łatwych sposobów nie jest przechowywanie danych wyjściowych w zmiennej, ale bezpośrednie iterowanie po nich za pomocą pętli while / read.
Coś jak:
grep xyz abc.txt | while read -r line ; do
echo "Processing $line"
# your code goes here
done
Istnieją różnice w tym schemacie w zależności od tego, czego dokładnie szukasz.
Jeśli chcesz zmienić zmienne wewnątrz pętli (i chcesz, aby ta zmiana była widoczna poza nią), możesz użyć podstawiania procesów zgodnie z odpowiedzią fedorqui :
while read -r line ; do
echo "Processing $line"
# your code goes here
done < <(grep xyz abc.txt)
while read p || [[ -n $p ]]; do ...
(zapożyczone ze stackoverflow.com/questions/1521462/… )
Możesz wykonać następującą while read
pętlę, która będzie zasilana wynikiem grep
komendy z wykorzystaniem tzw. Podstawienia procesu:
while IFS= read -r result
do
#whatever with value $result
done < <(grep "xyz" abc.txt)
W ten sposób nie musisz przechowywać wyniku w zmiennej, ale bezpośrednio „wstrzyknąć” jej wyjście do pętli.
Zwróć uwagę na użycie IFS=
i read -r
zgodnie z zaleceniami w BashFAQ / 001: Jak odczytać plik (strumień danych, zmienną) wiersz po wierszu (i / lub pole po polu)? :
Opcja -r do odczytu zapobiega interpretacji odwrotnego ukośnika (zwykle używana jako para znaków nowego wiersza z odwrotnym ukośnikiem, aby kontynuować w wielu wierszach lub uniknąć ograniczników). Bez tej opcji wszystkie znaki ukośnika odwrotnego bez zmiany znaczenia w danych wejściowych zostaną odrzucone. Prawie zawsze powinieneś używać opcji -r z read.
W powyższym scenariuszu IFS = zapobiega przycinaniu wiodących i końcowych białych znaków. Usuń go, jeśli chcesz ten efekt.
Jeśli chodzi o zastępowanie procesu, jest to wyjaśnione na stronie hakerów bash :
Podstawianie procesu to forma przekierowania, w której dane wejściowe lub wyjściowe procesu (pewna sekwencja poleceń) pojawiają się jako plik tymczasowy.
for
wersję. Próbowałem wykonać pętlę, "${$(grep xyz abc.txt)[@]}"
jak na stackoverflow.com/a/14588210/1983854, ale nie udało się. Zostawiam więc tylko pierwszą wersję.
zsh
, gdzie ten rodzaj zagnieżdżenia prawdopodobnie działa).
while IFS= read -r result <&3
idone 3< <(grep ...
Sugerowałbym użycie awk zamiast grep + coś innego tutaj.
awk '$0~/xyz/{ //your code goes here}' abc.txt
//your code goes here
?
Bez żadnej iteracji z opcją grep --line-buffered:
your_command | grep --line-buffered "your search"
Przykład z życia wzięty z wyprowadzeniem polecenia debugowania routera w Symfony PHP Framework w celu grepowania wszystkich tras związanych z „api”:
php bin/console d:r | grep --line-buffered "api"
tail -f some.log
w moim przypadku) ...
Często kolejność przetwarzania nie ma znaczenia. GNU Parallel jest stworzone dla tej sytuacji:
grep xyz abc.txt | parallel echo do stuff to {}
Jeśli przetwarzanie bardziej przypomina:
grep xyz abc.txt | myprogram_reading_from_stdin
i myprogram
jest powolny, możesz biec:
grep xyz abc.txt | parallel --pipe myprogram_reading_from_stdin
grep -o
tego rodzaju rzeczy.-o
Flaga będzie oddać tylko tekst, który odpowiada z jednego meczu na linię produkcji. (Nie jest wyczerpująca, więcecho aaa |grep 'a*'
podaje tylko „aaa” i pomija trzy częściowe dopasowania „”, „a” i „aa”)