Tôi đã tìm ra sed
câu trả lời không lâu sau khi tôi đăng câu hỏi này; không ai khác đã sử dụng sed
cho đến nay nó là:
sed '$!N;/^\(.*\)\n\1$/d;P;D'
Một chút chơi xung quanh với vấn đề chung hơn (về việc xóa các dòng trong bộ ba? Hoặc bốn hoặc năm?) Đã cung cấp giải pháp mở rộng sau:
sed -e ':top' -e '$!{/\n/!{N;b top' -e '};};/^\(.*\)\n\1$/d;P;D' temp
Mở rộng để loại bỏ ba lần dòng:
sed -e ':top' -e '$!{/\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1$/d;P;D' temp
Hoặc để loại bỏ bốn dòng:
sed -e ':top' -e '$!{/\n.*\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1\n\1$/d;P;D' temp
sed
có một lợi thế bổ sung so với hầu hết các tùy chọn khác, đó là khả năng thực sự hoạt động trong luồng, không cần nhiều bộ nhớ hơn so với số lượng dòng thực tế cần kiểm tra trùng lặp.
Như cuonglm đã chỉ ra trong các bình luận , việc đặt ngôn ngữ thành C là cần thiết để tránh thất bại trong việc loại bỏ đúng các dòng chứa các ký tự nhiều byte. Vì vậy, các lệnh trên trở thành:
LC_ALL=C sed '$!N;/^\(.*\)\n\1$/d;P;D' temp
LC_ALL=C sed -e ':top' -e '$!{/\n/!{N;b top' -e '};};/^\(.*\)\n\1$/d;P;D' temp
LC_ALL=C sed -e ':top' -e '$!{/\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1$/d;P;D' temp
# Etc.
C
, nếu không, trong miền địa phương nhiều byte, ký tự không hợp lệ trong miền địa phương đó khiến lệnh bị lỗi.