Lý do tại sao
tac file | grep foo | head -n 1
Không dừng lại ở trận đấu đầu tiên là vì bộ đệm.
Thông thường, head -n 1thoát sau khi đọc một dòng. Vì vậy, grepnên lấy SIGPIPE và thoát cũng như ngay khi nó viết dòng thứ hai.
Nhưng điều xảy ra là bởi vì đầu ra của nó không đi đến một thiết bị đầu cuối, nên grepđệm nó. Đó là, nó không viết nó cho đến khi nó tích lũy đủ (4096 byte trong thử nghiệm của tôi với GNU grep).
Điều đó có nghĩa là nó grepsẽ không thoát ra trước khi nó đã ghi 8192 byte dữ liệu, vì vậy có lẽ khá nhiều dòng.
Với GNU grep, bạn có thể làm cho nó thoát ra sớm hơn bằng cách sử dụng --line-bufferednó để ghi nó ngay khi chúng được tìm thấy bất kể có đi đến thiết bị đầu cuối hay không. Vì vậy, grepsau đó sẽ thoát khỏi dòng thứ hai nó tìm thấy.
Nhưng với GNU grepdù sao đi nữa, bạn có thể sử dụng -m 1thay vì như @terdon đã hiển thị, sẽ tốt hơn khi nó thoát ở trận đấu đầu tiên.
Nếu bạn grepkhông phải là GNU grep, thì bạn có thể sử dụng sedhoặc awkthay vào đó. Nhưng tac là một lệnh GNU, tôi nghi ngờ bạn sẽ tìm thấy một hệ thống với tacnơi grepkhông phải là GNU grep.
tac file | sed "/$pattern/!d;q" # BRE
tac file | P=$pattern awk '$0 ~ ENVIRON["P"] {print; exit}' # ERE
Một số hệ thống phải tail -rlàm điều tương tự như GNU tac.
Lưu ý rằng, đối với các tệp thông thường (có thể tìm kiếm) tacvà tail -rhiệu quả vì chúng đọc các tệp ngược, chúng không chỉ đọc tệp đầy đủ trong bộ nhớ trước khi in ngược (như cách tiếp cận sed của @ slm hoặc tactrên các tệp không thông thường) .
Trên các hệ thống không có sẵn tachoặc không tail -rcó sẵn, các tùy chọn duy nhất là triển khai đọc ngược bằng tay với các ngôn ngữ lập trình như perlhoặc sử dụng:
grep -e "$pattern" file | tail -n1
Hoặc là:
sed "/$pattern/h;$!d;g" file
Nhưng những điều đó có nghĩa là tìm tất cả các trận đấu và chỉ in cái cuối cùng.