Я розробив sed
відповідь недовго після того, як опублікував це запитання; ще ніхто не використовував її до sed
цього часу, ось це:
sed '$!N;/^\(.*\)\n\1$/d;P;D'
Трохи розібравшись із загальнішою проблемою (як щодо видалення рядків у наборах по три? Або чотири чи п’ять?), Було запропоновано таке розширюване рішення:
sed -e ':top' -e '$!{/\n/!{N;b top' -e '};};/^\(.*\)\n\1$/d;P;D' temp
Розширено для видалення трійки рядків:
sed -e ':top' -e '$!{/\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1$/d;P;D' temp
Або видалити квадратики ліній:
sed -e ':top' -e '$!{/\n.*\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1\n\1$/d;P;D' temp
sed
має додаткову перевагу перед більшістю інших опцій, що полягає в його здатності по-справжньому працювати в потоці, не потрібно більше пам’яті пам’яті, ніж фактична кількість рядків, що перевіряються на дублікати.
Як в коментарях зазначалося cuonglm , встановлення локальної точки на C необхідно, щоб уникнути збоїв у належному видаленні рядків, що містять багатобайтові символи. Отже команди вище стають:
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
, інакше в багатобайтовій мові недійсний символ у цій мові може призвести до відмови команди.