Làm thế nào để tìm kiếm văn bản trong một tập tin bỏ qua dòng mới?


11

Tôi muốn tìm kiếm văn bản có thể được chia thành nhiều dòng trong một tệp. Một grep sẽ bỏ qua ngắt dòng và trả về nhịp phù hợp của các dòng.

ví dụ: tôi sẽ tìm kiếm is an example filevà hy vọng nó sẽ được tìm thấy trong tệp sau:

Đây là
một
tập tin ví dụ.

Không phụ thuộc vào không gian dẫn đầu hoặc dấu vết, hoàn toàn bỏ qua tất cả các dạng của khoảng trắng có thể là tốt nhất (lý tưởng nhất, coi bất kỳ chuỗi khoảng trắng nào là một khoảng trắng).


Một giải pháp không lý tưởng là tr '\n' ' ' | grep, phân biệt giữa trận đấu và không khớp, nhưng không hiển thị trận đấu, cũng không xử lý tốt các tệp lớn.


trên SO (không có câu trả lời dứt khoát): stackoverflow.com/q/1858312/1449460
Nikana Reklawyks

Một ghi chú bên lề, tìm kiếm của emacs dường như thực hiện công việc ( isearch-forward)
Nikana Reklawyks

Vim cũng vậy : /This\_sis. Để biết thêm chi tiết : :help \_s.
lcd047

Thêm dòng này vào cuối dòng tìm kiếm của bạn: tr -n "\ n" Điều này sẽ xóa tất cả các dòng mới. Hy vọng điều này giúp đỡ!
Dan Howel

Câu trả lời:


12

GNU grepcó thể làm điều đó

grep -z 'is\san\sexample\sfile.' file

Để thực hiện một số điểm phát sinh trong các nhận xét, có một số sửa đổi đối với tập lệnh:

 grep -oz '^[^\n]*\bis\s*an\s*example\s*file\.[^\n]*' file

Về các tệp khổng lồ tôi không có trí tưởng tượng về giới hạn bộ nhớ nhưng trong trường hợp có vấn đề, bạn có thể sử dụng miễn phí sed

sed '/\bis\b/{
          :1
          N
          /file\.\|\(\n.*\)\{3\}/!b1
         }
     /\<is\s*an\s*example\s*file\./p
     D' file

giữ không quá 4 dòng (vì 4 từ trong mẫu) trong bộ nhớ ( \(\n.*\)\{3\}).


5
Như tôi chắc chắn bạn biết, -ztùy chọn này grepsẽ coi các dòng mới là các ký tự văn bản thông thường và tìm các byte nul để tách các bản ghi. Trong một tệp văn bản không có byte nul (nghĩa là trường hợp điển hình), grep -zsẽ coi toàn bộ tệp là một dòng. Vì vậy, (1) điều này đặt ra câu hỏi là nó có thể xử lý các tệp lớn như thế nào và (2) nếu tìm thấy kết quả khớp, nó sẽ ghi ra toàn bộ tệp, không đưa ra manh mối nào về vị trí của trận đấu. Ngoài ra (3) OP cho biết, lý tưởng nhất, đối xử với bất kỳ chuỗi khoảng trắng nào dưới dạng một khoảng trắng, vì vậy bạn nên sử dụng \s+và thêm vào -E.
G-Man nói 'Phục hồi Monica'

1
@ G-Man Cảm ơn bạn đã bình luận. Xin vui lòng xem câu trả lời chỉnh sửa.
Costas

1
(0) À , -o; Tôi tiếp tục quên về điều đó. Cách thông minh để sử dụng nó. (1) grepCâu trả lời mới của bạn bắt đầu ^[\n]*; đó là một lỗi đánh máy cho [^\n]*. (2) Tôi \s+cố tình nói .  be\s*littlesẽ phù hợp belittle, và care\s*lesssẽ phù hợp careless. Nhưng tôi đoán đó là một vấn đề nhỏ. Và, nếu bạn không muốn sử dụng -E, bạn có thể sử dụng phiên bản của người nghèo \s+, cụ thể là , \s\s*. (3) sedLệnh hay. Nó có thể thất bại nếu có các dòng trống (vì vậy cụm từ bốn từ có thể trải rộng hơn bốn dòng); Tôi đã có thể khắc phục điều đó bằng cách thêm s/\n\s*\n/\n/.
G-Man nói 'Phục hồi Monica'

@ G-Man Cảm ơn bạn. Nhận xét của bạn rất hữu ích. Tôi đã cố gắng đăng nhiều hoặc ít mã di động bởi vì các thành viên nổi tiếng mỗi khi thúc đẩy tôi làm như vậy. Dù sao, ngay cả khi không có -Ebạn thép có thể sử dụng +trong \s\+hình thức. Các dòng trống bên trong mô hình dường như là một kế hoạch.
Costas

Tôi đã nghĩ đến các tài liệu văn bản được phân trang, như RFC - ISTR rằng các trang man trông giống như vậy trên một số hệ thống (hoặc đã làm ) - nhưng, theo tôi nghĩ thêm, hầu hết các tài liệu đó đều có tiêu đề trang và / hoặc chân trang (s) sẽ cần phải được loại bỏ trước khi bạn có thể hy vọng cho grephọ cụm từ.
G-Man nói 'Phục hồi Monica'

7

Thử cái này xem sao:

pcregrep -M '\bThis\s+is\b' <<EOT
This
is
an example
file.
EOT

Tôi có phải gõ \s5 lần nếu tôi tìm kiếm "đây là một mẫu rất dài" không?
Nikana Reklawyks 18/05/2015

1
Có: điểm \sphù hợp với không gian và dòng mới là "khoảng trắng".
lcd047

Ý tôi là, nếu tập tin là gì This\nis a very\nlong pattern, và tôi không biết nơi nào có thể xảy ra ngắt dòng. Tôi phải tìm kiếm This\sis\sa\svery\slong\spattern, phải không? (trở nên tẻ nhạt khi chiều dài của mẫu tăng hoặc dán từ nơi khác)
Nikana Reklawyks

2
Sau đó, bạn làm điều đó như thế này : pcregrep -M "$( echo 'This is a very long pattern' | sed 's/ /\\s+/g' )" file.
lcd047
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.