Cách chọn lần xuất hiện đầu tiên giữa hai mẫu bao gồm chúng


27

Làm thế nào tôi có thể chọn lần xuất hiện đầu tiên giữa hai mẫu bao gồm chúng. Tốt nhất là sử dụng sedhoặc awk.

Tôi có:

text
something P1 something
content1
content2
something P2 something
text
something P1 something
content3
content4
something P2 something
text

Tôi muốn sự xuất hiện đầu tiên của các dòng giữa P1 và P2 (bao gồm dòng P1 và dòng P2):

something P1 something
content1
content2
something P2 something

Câu trả lời:


22
sed '/P1/,/P2/!d;/P2/q'

... sẽ thực hiện công việc một cách hợp lý bằng cách dxóa tất cả các dòng !không nằm trong phạm vi, sau đó qlần đầu tiên gặp nó ở cuối phạm vi. Nó không thất bại đối với P2 trước P1 và nó không yêu cầu cú pháp cụ thể của GNU để viết đơn giản.


Xuất sắc! Tốt hơn nhiều so với của tôi.
muru

1
@muru - Việc tránh các cơn co thắt thường dễ dàng hơn nếu bạn cố gắng nhắm mục tiêu tự động in - hãy để chu trình làm việc cho bạn. Dù sao đó cũng là thói quen của tôi. Tôi nghĩ rằng nó có thể được mô tả tốt nhất dưới dạng cắt tỉa so với phương pháp chọn - tôi có xu hướng kết thúc phủ nhận một mẫu hơn là tìm kiếm nó.
mikeerv

Điều này sẽ treo khi xử lý kích thước tệp lớn.
Brain90

@ Brain90 - không nên. nếu bạn có thể tái tạo một cách đáng tin cậy khiếu nại của mình, bạn nên giải quyết cho người duy trì sed... đó là một lỗi trong quá trình sedbạn đang chạy, và không phải trong đoạn mã trên.
mikeerv

1
@mikeerv Tôi sẽ không nói nếu tôi không. Mối quan tâm của bạn về việc tôi có quan tâm đến một vài nhân vật hay không là kỳ lạ: Tôi quan sát thấy biểu hiện sed hoạt động cả có và không có /P2/qtrên hệ thống của tôi; đó là nó. Tôi tò mò về một cái gì đó và muốn chia sẻ những gì tôi tìm thấy.
Alexej Magura

8

với awk

awk '/P1/{a=1};a;/P2/{exit}' file
something P1 something
content1
content2
something P2 something

8

Trong sed:

sed -n '/P1/,/P2/p; /P2/q'
  • -ntriệt tiêu việc in mặc định và bạn in các dòng giữa các dải địa chỉ phù hợp bằng plệnh.
  • Thông thường, điều này sẽ phù hợp với cả hai phần, vì vậy bạn thoát ( q) khi lần đầu tiên P2khớp.

Điều này sẽ thất bại nếu P2đến trước P1. Để xử lý trường hợp đó, hãy thử:

sed -n '/P1/,/P2/{p; /P2/q}'

1
Tôi không đồng ý; Câu trả lời của mikeerv không tốt hơn câu trả lời của bạn.
G-Man nói 'Phục hồi Monica'

@ g-man - pshaw. Nhưng tôi chỉ nghĩ điều tương tự.
mikeerv

1
@gman - Không. giờ thì tôi đã hiểu. Mỏ cách tốt hơn. không {ngăn xếp}!
mikeerv

1

Nếu bạn muốn tự bỏ qua các mẫu, đây là awkphiên bản:

awk '/P2/ {exit} /P1/ {f=1; next} f' file

Làm việc cho tôi. Bạn có thể thêm một số thông tin về cách hoạt động của lệnh?
0xAffe

1

Một awkgiải pháp đơn giản hơn (sắp xếp giữa chừng câu trả lời của iruvar và  câu trả lời của muru , nhưng không sử dụng biến):

awk '/P1/,/P2/ { print }  /P2/ { exit }'

và, như muru đã lưu ý, nếu P2 đầu tiên xuất hiện trước P1 đầu tiên, điều này sẽ không in gì cả.

Tất nhiên, nếu bạn muốn in tất cả các phạm vi P1-P2:

something P1 something
content1
content2
something P2 something
something P1 something
content3
content4
something P2 something

chỉ cần bỏ đi exitphần:

awk '/P1/,/P2/ { print }'

1
awk '/P1/,/P2/{print;f=1} f&&/P2/{exit}' data

Thoát ngay sau khi in, không phải trước.


0

Để tự bỏ qua các mẫu và chỉ hiển thị khối khớp đầu tiên trong một GNU GNU:

sed -nre '/STARTPATTERN/ {:a;n;/ENDPATTERN/{b;};p;ba}' file
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.