2013-05-01 36 views
92

Tôi có một số dòng lấy ra từ một tập tin sau khi chạy lệnh grep như sau:Làm thế nào để xử lý mỗi dòng nhận như là kết quả của lệnh grep

var=`grep xyz abc.txt` 

Hãy nói rằng tôi có 10 dòng trong đó bao gồm xyz kết quả là.

Bây giờ tôi cần xử lý từng dòng tôi nhận được do lệnh grep. Làm thế nào để tôi tiến hành việc này?

+2

Không ai trong số các câu trả lời ở đây đề cập đến sức mạnh của 'grep -o' cho các loại điều này. Cờ '-o' sẽ trả lại _only_ văn bản phù hợp, với một kết quả phù hợp trên mỗi dòng đầu ra.(Nó không đầy đủ, do đó, 'echo aaa | grep 'a *'' chỉ cung cấp cho bạn "aaa" và bỏ qua ba phần khớp "", "a" và "aa") –

Trả lời

169

Một trong những cách dễ dàng là không lưu trữ đầu ra trong một biến, nhưng trực tiếp lặp lại 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ó những khác biệt về chương trình này phụ thuộc vào chính xác những gì bạn đang sau.

Nếu bạn cần thay đổi các biến bên trong vòng lặp (và có sự thay đổi đó là bên ngoài có thể nhìn thấy của nó), bạn có thể sử dụng thay thế tiến trình như đã nêu trong fedorqui's answer:

while read -r line ; do 
    echo "Processing $line" 
    # your code goes here 
done < <(grep xyz abc.txt) 
+0

nếu không có dòng nào với xyz? –

+0

Sau đó, không có gì xảy ra, vòng lặp không chạy. – Mat

+10

Vấn đề với phương pháp này là (vì đường ống) mọi thứ bên trong vòng lặp nằm trong một vỏ bọc, do đó, thiết lập các biến được định nghĩa bên ngoài vòng lặp trong vòng lặp không làm cho các giá trị của chúng có sẵn sau vòng lặp! –

16

Bạn có thể làm while read vòng sau, sẽ được nuôi dưỡng 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 cần phải lưu trữ các kết quả trong một biến, nhưng trực tiếp "tiêm" đầu ra của nó đến vòng lặp.


Lưu ý việc sử dụng IFS=read -r theo các khuyến nghị trong BashFAQ/001: How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?:

Các tùy chọn -r để đọc ngăn chặn việc giải thích xuyệc ngược (thường được sử dụng như một cặp dấu chéo ngược xuống dòng, để tiếp tục qua nhiều dòng hoặc để thoát khỏi dấu phân tách). Nếu không có tùy chọn này, bất kỳ dấu gạch chéo ngược không thoát nào trong đầu vào sẽ bị hủy. Bạn hầu như luôn luôn nên sử dụng tùy chọn -r khi đọc.

Trong trường hợp trên IFS = ngăn chặn cắt bớt khoảng trắng hàng đầu và đuôi . Loại bỏ nó nếu bạn muốn hiệu ứng này.

Về quá trình thay thế, nó được giải thích trong bash hackers page:

Process thay thế là một hình thức chuyển hướng nơi đầu vào hoặc đầu ra của một quá trình (một số chuỗi các lệnh) xuất hiện như một tạm thời tệp.

+4

Thứ hai là chính xác (mặc dù 'read -r' an toàn hơn); đầu tiên chỉ hoạt động với các dòng không có khoảng trắng. – chepner

+0

OK, tôi đã loại bỏ phiên bản 'for'. Đã cố gắng thực hiện một vòng lặp trên '" $ {$ (grep xyz abc.txt) [@]} "' như trong http://stackoverflow.com/a/14588210/1983854 nhưng không thể. Vì vậy, tôi chỉ cần rời khỏi phiên bản đầu tiên. – fedorqui

+1

Bạn không thể áp dụng mở rộng tham số cho một thay thế lệnh (trừ khi bạn đang sử dụng 'zsh', nơi mà loại tổ có thể hoạt động). – chepner

5

Tôi khuyên bạn nên sử dụng awk thay vì grep + cái gì khác ở đây.

awk '$0~/xyz/{ //your code goes here}' abc.txt

+2

Ngay cả 'awk'/xyz/''sẽ hoạt động. – fedorqui

+0

Làm cách nào bạn tham chiếu đến dòng được tìm thấy hoàn chỉnh trong '// mã của bạn đến đây'? – user857990

+1

@ user857990 Toàn bộ dòng được biểu thị bằng $ 0 trong AWK. –

Các vấn đề liên quan