grep --before-context 5
hiển thị 5 dòng trước trận đấu.
Tôi muốn thể hiện mọi thứ trước trận đấu.
Làm grep --before-context 99999999
sẽ làm việc nhưng nó không ... rất chuyên nghiệp.
Làm thế nào để hiển thị tất cả các tập tin lên đến trận đấu?
grep --before-context 5
hiển thị 5 dòng trước trận đấu.
Tôi muốn thể hiện mọi thứ trước trận đấu.
Làm grep --before-context 99999999
sẽ làm việc nhưng nó không ... rất chuyên nghiệp.
Làm thế nào để hiển thị tất cả các tập tin lên đến trận đấu?
Câu trả lời:
Sed là tốt hơn cho điều đó.
Cứ làm đi:
sed '/PATTERN/q' FILE
Nó hoạt động như thế này:
Đối với mỗi dòng, chúng tôi xem nếu nó phù hợp /PATTERN
:
Đây là giải pháp hiệu quả nhất, vì ngay khi nhìn thấy PATTERN
, nó đã thoát ra. Nếu không q
, sed sẽ tiếp tục đọc phần còn lại của tập tin và không làm gì với nó. Đối với các tập tin lớn, nó có thể làm cho một sự khác biệt.
Thủ thuật này cũng có thể được sử dụng để mô phỏng head
:
sed 10q FILE
sed '/PATTERN/Q' FILE
sẽ bỏ qua dòng phù hợp. Q
là một phần mở rộng GNU, vì vậy nó sẽ không hoạt động với bất kỳ sed nào.
sed
có thể thay thế hầu hết các chức năng của grep.
sed -n '1,/<pattern>/ p' <file>
Điều này có nghĩa là in từ dòng đầu tiên cho đến khi mẫu được khớp.
Một vài ví dụ
sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2
in lên và bao gồm cả trận đấu:
awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename
in lên NHƯNG KHÔNG bao gồm trận đấu:
awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename
Q
Afaik mát mẻ nhưng cụ thể của gnu, sed -n '/pattern/!p;//q'
sẽ dễ mang theo hơn.
!
làm cho p
áp dụng đối với dòng không phù hợp pattern
, nhưng sau đó //q
bối rối cho tôi ...
//
có nghĩa là "biểu thức chính quy trước đó" (tôi nghĩ nó có nghĩa là "khớp với chuỗi rỗng"). Tôi nghĩ rằng một phiên bản ngắn hơn của cùng một giải pháp là : sed -n '/pattern/q;p
?
Các grep
phương thức GNU thuần túy sau đây không hiệu quả.
Tìm kiếm mọi thứ cho đến phiên bản đầu tiên của chuỗi " foo " trong thanh tệp , sử dụng ba grep
s:
grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar
Phù hợp với phiên bản cuối cùng của " foo ":
grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar
Lưu ý: chi tiết cuối cùng grep
có thể được tìm thấy trong: Regex (grep) cho tìm kiếm nhiều dòng cần thiết .
grep
giây (+ pcre) khi vấn đề chỉ đơn giản là chạy một lệnh sed
gọi duy nhất : sed 'x;/./G;//!x;/foo/p;//s/.*//;x;d'
??
sed
mã của bạn có vẻ đáng để trả lời, hoặc có thể được thêm vào một trong những mã khác. Re 7 grep
s: Bởi vì không có grep
câu trả lời ... (cộng với, câu trả lời giúp thể hiện tại sao không.)
Thêm vào câu trả lời của Mikel ở trên ...
Để in tất cả các dòng lên đến, nhưng không bao gồm , dòng đầu tiên FILE
chứa PATTERN
, hãy thử:
sed '/.*PATTERN.*/{s///;q;}' FILE
Điều này khớp với toàn bộ dòng chứa mẫu, thay thế nó bằng một dòng trống, sau đó thoát ra mà không xử lý phần còn lại của tệp.
Kịch bản sau:
Cách dễ nhất / rõ ràng nhất mà tôi có thể nghĩ ra để ngăn việc in thêm một dòng mới ở cuối (không liên quan đến công cụ khác), là chạy lại sed và xóa dòng cuối cùng mới:
sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'
... và vì hiện tại chúng tôi đang xóa dòng đó, công việc trước đây của chúng tôi là không cần thiết và chúng tôi có thể đơn giản hóa để:
sed '/PATTERN/q' FILE | sed '$d'
sed
lời mời duy nhất .
tcsh
và một bash
bí danh, tôi cần phải chắc chắn rằng tôi có một giải pháp một dòng tương đối ngắn gọn, hoạt động trong cả tiêu chuẩn và GNU sed
(cho tính di động); tất cả các yêu cầu mà sự đóng góp của bạn rất có thể đã đáp ứng. Là một người sử dụng sed
rất hiếm khi, yêu cầu quan trọng nhất của tôi là một cái gì đó mà tôi có thể nhanh chóng hiểu khi tôi muốn dễ dàng chỉnh sửa hoặc tái mục đích đó năm kể từ bây giờ.
Đối với những người chọn chỉ nhớ các công cụ cơ bản trong công việc hàng ngày và sẵn sàng chấp nhận các giải pháp kém thanh lịch và kém hiệu quả hơn:
head -n $(grep -n pattern filename | cut -d: -f1) filename
Nếu lệnh này là cho một kịch bản thì tôi sẽ tìm kiếm các giải pháp thanh lịch hơn (và có thể hiệu quả). Nếu đây là lệnh một lần hoặc kịch bản vứt đi thì tôi không quan tâm.
Bạn cũng có thể sử dụng một trong những điều sau đây
tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac
hoặc là
tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac
hoặc là
tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac
Tùy chọn đầu tiên rất giống với những gì OP đề xuất, chỉ đảm bảo rằng ti hiển thị đủ các dòng trước ngữ cảnh bằng cách đếm các dòng trong tệp
Tùy chọn thứ hai tìm kiếm số dòng của trận đấu đầu tiên (bạn cũng có thể thay đổi số đó bằng cách thay đổi 'đầu' bên trong) và sử dụng đầu trên số đó
Tùy chọn cuối cùng thay thế tất cả các dòng mới bằng trận đấu và thay thế hai trận đấu liền kề bằng một dòng mới. Đầu ra của điều này là một dòng cho mỗi khối văn bản giữa hai kết quả khớp. Sau đó, nó sử dụng 'head' để chọn dòng đầu tiên (thay đổi khối văn bản cho đến khi khớp đầu tiên) khớp và hơn là truyền lại mỗi trận đấu sang một dòng mới. tùy chọn này chỉ hoạt động nếu tệp có định dạng sau
pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern
texttexttext
texttexttexttexttexttexttexttexttext
và kể từ đó trở đi
sed
lệnh đó ở phía dưới là loại sởn gai ốc.