Xóa các dòng không bắt đầu bằng một mẫu khỏi một nhóm mẫu nhất định


10

Tôi có một tệp chứa dữ liệu như thế này:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc

.. --.

Câu hỏi: Tôi muốn xóa bất kỳ dòng nào không bắt đầu bằng các chuỗi sau:

report  
-th  
-to

điều đó có nghĩa là đầu ra mong muốn sẽ loại bỏ tất cả các dấu chấm và băm không mong muốn ở giữa và sẽ trông như thế này:

report aaaaaaaa  
-th bbbbbbbbb  
-to ccccccccc

sed/ awk/ grep/ vv bất kỳ giải pháp nào sẽ làm việc.

Câu trả lời:


15

Sử dụng sedđể sửa đổi tập tin tại chỗ:

sed -i '/^\(report\|-t\(h\|o\)\)/!d' your_file

Điều này hướng dẫn sedxóa tất cả các dòng không phù hợp với mẫu. Bản thân mẫu là ^(bắt đầu của dòng), theo sau là reporthoặc -ttheo sau hhoặc o.

Bạn nên lưu ý rằng đây không phải là sửa đổi tại chỗ thực tế: sedtạo một bản sao lưu tạm thời và ghi đè lên tệp gốc với nó.

Nếu bạn muốn sedgiữ một bản sao lưu của tệp gốc (có thể là một ý tưởng tốt nếu tệp chứa dữ liệu quan trọng), hãy cung cấp cho công -itắc một phần mở rộng để tạo tệp sao lưu:

sed -i'.bak' -e '/^\(report\|-t\(h\|o\)\)/!d' your_file

sẽ sửa đổi your_filevà tạo một bản sao lưu của bản gốc được gọi your_file.bak.

Một ghi chú bên

Xin đừng hiểu sai ý định của tôi hoặc vi phạm điều này, nhưng tôi nhận thấy rằng bạn có nhiều câu hỏi liên quan đến regex / xử lý văn bản tương tự. Tôi khuyên bạn nên bắt đầu học sed, awkgreptự mình giúp tăng tốc năng suất của bạn. Một lần nữa, đừng hiểu sai ý tôi, tôi rất vui khi được giúp đỡ (như hầu hết mọi người ở đây); chỉ là tôi nghĩ rằng bạn sẽ được hưởng lợi rất nhiều từ việc chọn những công cụ này để sử dụng hàng ngày.

Chỉ để chứng minh mức độ hữu ích của mọi người xung quanh đây, hãy xem xét đề xuất của @ slm trong các bình luận bên dưới và thoải mái ghé qua phòng chat này bất cứ lúc nào để đặt câu hỏi.


1
Biểu hiện thường xuyên của bạn có vẻ khó hiểu không cần thiết. Tôi nghĩ rằng bạn thực sự sử dụng nhiều ký tự hơn nếu bạn chỉ liệt kê rõ ràng ba tùy chọn.
nispio

1
@nispio Tôi biết, nhưng nó có thể hiệu quả hơn nếu tệp được đề cập là lớn.
Joseph R.

Hấp dẫn. Tôi đã luôn đo regexps về độ dài hoặc khả năng đọc. Tôi chưa bao giờ nghĩ nhiều đến tốc độ thực hiện. Tôi không nghĩ rằng tôi biết đủ về cách họ được đánh giá để đánh giá thế nào là nhanh, nhưng tôi cho rằng đó cũng là việc thực hiện cụ thể, phải không?
nispio

3
Lặp lại những gì Joseph nói về việc sẵn sàng giúp đỡ, nếu bạn có những câu hỏi chung không phù hợp với phong cách Hỏi & Đáp, bạn luôn có thể thử trò chuyện với chúng tôi trong phòng trò chuyện cho trang web này. chat.stackexchange.com/room/26/unix-and-linux . Một số người trong chúng ta sống ở đó 8-)
slm

@slm Cảm ơn bạn vì điều này. Tôi sẽ thêm nó vào câu trả lời của tôi.
Joseph R.

10

Bạn có thể sử dụng grep đơn giản cho việc này:

$ grep -e '^report\|^-th\|^-to' filename

1
Đó không phải là nhiều tiền tiết kiệm, nhưng bạn có thể kết hợp -th/ -tovào -t[ho].
Kevin

grep -ehoặcegrep
Olivier Dulac

2

Sử dụng sed:

sed -n -e '/^report\|^-th\|^-to/p' filename

Đó không phải là nhiều tiền tiết kiệm, nhưng bạn có thể kết hợp -th/ -tovào -t[ho].
Kevin

1
@Kevin Đúng vậy. Xem cuộc trò chuyện của tôi với Joseph R. trong các bình luận cho câu trả lời của anh ấy.
nispio

2

Sử dụng awk:

awk '/^report|^-t[ho]/' file

Đó không phải là nhiều tiền tiết kiệm, nhưng bạn có thể kết hợp -th/ -tovào -t[ho].
Kevin

1

Người hỏi đã đưa ra hai điểm:

  • muốn xóa bất kỳ dòng nào không bắt đầu bằng "báo cáo" hoặc "-th" hoặc "-to".
  • đầu ra mong muốn sẽ loại bỏ "tất cả các dấu chấm và băm không mong muốn ở giữa (sic)"

Các giải pháp, tại thời điểm này, giải quyết điểm đầu tiên và do đó cũng là điểm thứ hai. Nhưng giả sử tập tin lớn hơn và trông như sau:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc
anything else
.. --.
-tp ddd
-tq eee
     -  -----

Sẽ không giải quyết điểm thứ hai của OP có cần thiết không?

sed -r -i.bak '/^[ |.|-]*$/d' input-file 

thực hiện công việc loại bỏ các dòng có lẽ không mong muốn chỉ chứa khoảng trắng, dấu chấm và dấu gạch ngang và giữ lại phần còn lại, bất kể đó là gì.
Tôi nghĩ rằng rủi ro của một trong hai cách tiếp cận là bản chất của tệp không được xác định đúng.


0

Sử dụng Perl:

perl -ne 'print if /^report|^-t[ho]/' filename > newfile

hoặc, để chỉnh sửa tại chỗ (như sed, perlcũng sẽ tạo một bản sao lưu tạm thời để điều này không đúng trong chỉnh sửa tại chỗ ):

perl -i.bak -ne 'print if /^report|^-t[ho]/' filename

Điều đó sẽ tạo một bản sao của tệp gốc được gọi filename.bakvà ghi đè lên tệp gốc của bạn bằng phiên bản đã chỉnh sửa.

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.