Làm thế nào để loại bỏ các dòng trùng lặp với awk trong khi giữ các dòng trống?


13

awkLệnh bên dưới loại bỏ tất cả các dòng trùng lặp như được giải thích ở đây :

awk '!seen[$0]++'

Nếu văn bản chứa các dòng trống, tất cả trừ một dòng trống sẽ bị xóa.

Làm cách nào tôi có thể giữ tất cả các dòng trống trong khi xóa tất cả các dòng trùng lặp không trống, chỉ sử dụng awk? Xin vui lòng, cũng bao gồm một lời giải thích ngắn gọn.

Câu trả lời:


28

Một tùy chọn khác là kiểm tra NF, ví dụ:

awk '!NF || !seen[$0]++'

11

Hoặc

awk '!/./ || !seen[$0]++' file

Thủ thuật chính là như nhau, seen[$0]++tạo ra một mục trong seenmảng kết hợp có khóa là dòng hiện tại ( $0). Do đó, !seen[$0]++sẽ là sai nếu dòng này đã được nhìn thấy. Việc /./kiểm tra xem dòng có chứa bất kỳ ký tự không trống nào không, do đó !/./khớp với các dòng không trống. Kết hợp với || !seen[$0]++nó sẽ bỏ qua tất cả các dòng trùng lặp ngoại trừ các dòng trống và in phần còn lại.


Tôi nghĩ rằng đây đã là câu trả lời được chấp nhận. +1 để giải thích!
SS Anne

5
awk '/^[[:blank:]]*$/ { print; next; }; !seen[$0]++'

Tất cả bạn phải làm là kiểm tra một dòng trống (thực sự trống hoặc chỉ trống) trước.


5

Đây là một awkgiải pháp khác , tương tự như câu trả lời của @ Thor, ít súc tích hơn nhưng hiệu quả hơn:

awk '!NF {print;next}; !($0 in a) {a[$0];print}' file

Với điều này, chúng tôi chỉ kiểm tra a[$0]đã tồn tại hay chưa. Nếu không, khởi tạo nó sau đó in. Trong trường hợp này, chúng tôi không có bất kỳ tài liệu tham khảo, chuyển nhượng nào a[$0]nếu nó tồn tại.


Tôi không đo bất kỳ sự khác biệt đáng kể về thời gian với tệp thử nghiệm 288 dòng của mình. Tuy nhiên, mã của bạn chắc chắn nắm bắt được giải thưởng là dễ đọc nhất.
Serge Stroobandt
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.