Câu trả lời:
Một trong những cách dễ dàng là không lưu trữ đầu ra trong một biến, mà lặp lại trực tiếp trên nó với một vòng lặp while / read.
Cái gì đó như:
grep xyz abc.txt | while read -r line ; do
echo "Processing $line"
# your code goes here
done
Có các biến thể trong sơ đồ này tùy thuộc vào chính xác những gì bạn đang theo đuổi.
Nếu bạn cần thay đổi các biến trong vòng lặp (và có thể thấy sự thay đổi đó bên ngoài vòng lặp), bạn có thể sử dụng thay thế quy trình như được nêu trong câu trả lời của fedorqui's :
while read -r line ; do
echo "Processing $line"
# your code goes here
done < <(grep xyz abc.txt)
while read p || [[ -n $p ]]; do ...
(mượn từ stackoverflow.com/questions/1521462/ trộm )
Bạn có thể thực hiện while read
vòng lặp sau , sẽ được cung cấp bởi kết quả của grep
lệnh bằng cách sử dụng cái gọi là quá trình thay thế:
while IFS= read -r result
do
#whatever with value $result
done < <(grep "xyz" abc.txt)
Bằng cách này, bạn không phải lưu trữ kết quả trong một biến, nhưng trực tiếp "đưa" đầu ra của nó vào vòng lặp.
Lưu ý việc sử dụng IFS=
và read -r
theo các khuyến nghị trong BashFAQ / 001: Làm cách nào tôi có thể đọc từng tệp (luồng dữ liệu, biến) theo từng dòng (và / hoặc theo từng trường)? :
Tùy chọn -r để đọc ngăn chặn diễn giải dấu gạch chéo ngược (thường được sử dụng như một cặp dòng mới dấu gạch chéo ngược, để tiếp tục qua nhiều dòng hoặc để thoát các dấu phân cách). Nếu không có tùy chọn này, mọi dấu gạch chéo ngược không được giải quyết trong đầu vào sẽ bị loại bỏ. Bạn hầu như luôn luôn nên sử dụng tùy chọn -r với đọc.
Trong kịch bản trên IFS = ngăn chặn việc cắt xén khoảng trắng hàng đầu và dấu. Loại bỏ nó nếu bạn muốn hiệu ứng này.
Về việc thay thế quy trình, nó được giải thích trong trang tin tặc bash :
Thay thế quy trình là một hình thức chuyển hướng trong đó đầu vào hoặc đầu ra của một quá trình (một số chuỗi lệnh) xuất hiện dưới dạng một tệp tạm thời.
for
phiên bản. Đã thử thực hiện một vòng lặp "${$(grep xyz abc.txt)[@]}"
như trong stackoverflow.com/a/14588210/1983854 nhưng không thể. Vì vậy, tôi chỉ để lại phiên bản đầu tiên.
zsh
, nơi kiểu lồng đó có thể hoạt động).
while IFS= read -r result <&3
vàdone 3< <(grep ...
Tôi sẽ đề nghị sử dụng awk thay vì grep + một cái gì đó khác ở đây.
awk '$0~/xyz/{ //your code goes here}' abc.txt
//your code goes here
?
Không có bất kỳ sự lặp lại nào với tùy chọn grep được đệm dòng:
your_command | grep --line-buffered "your search"
Ví dụ thực tế với một lệnh gỡ lỗi của bộ định tuyến Symfony PHP Framework, để grep tất cả các tuyến liên quan đến "api":
php bin/console d:r | grep --line-buffered "api"
tail -f some.log
, trong trường hợp của tôi) ...
Thường thì thứ tự xử lý không quan trọng. GNU Parallel được tạo cho tình huống này:
grep xyz abc.txt | parallel echo do stuff to {}
Nếu bạn xử lý giống như:
grep xyz abc.txt | myprogram_reading_from_stdin
và myprogram
chậm thì bạn có thể chạy:
grep xyz abc.txt | parallel --pipe myprogram_reading_from_stdin
grep -o
loại điều này. Các-o
lá cờ sẽ trả lại chỉ văn bản mà các trận đấu, với một trận đấu trên mỗi dòng sản lượng. (Nó không đầy đủ, vì vậyecho aaa |grep 'a*'
chỉ cung cấp cho bạn "aaa" và bỏ qua ba phần khớp "", "a" và "aa")