sed
Odpowiedź wypracowałem niedługo po tym, jak opublikowałem to pytanie; jak dotąd nikt inny nie korzystał sed
:
sed '$!N;/^\(.*\)\n\1$/d;P;D'
Trochę zabawy z bardziej ogólnym problemem (co z usuwaniem linii w zestawach trzech? Lub czterech lub pięciu?) Zapewniło następujące rozszerzalne rozwiązanie:
sed -e ':top' -e '$!{/\n/!{N;b top' -e '};};/^\(.*\)\n\1$/d;P;D' temp
Rozszerzony, aby usunąć trzykrotnie linii:
sed -e ':top' -e '$!{/\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1$/d;P;D' temp
Lub usunąć quady z linii:
sed -e ':top' -e '$!{/\n.*\n.*\n/!{N;b top' -e '};};/^\(.*\)\n\1\n\1\n\1$/d;P;D' temp
sed
ma dodatkową przewagę nad większością innych opcji, a mianowicie jego zdolność do prawdziwego działania w strumieniu, przy czym nie potrzeba więcej pamięci niż rzeczywista liczba wierszy do sprawdzenia pod kątem duplikatów.
Jak zauważył cuonglm w komentarzach , ustawienie języka na C jest konieczne, aby uniknąć błędów w prawidłowym usuwaniu wierszy zawierających znaki wielobajtowe. Tak więc powyższe polecenia stają się:
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
, w przeciwnym razie w ustawieniach wielobajtowych niepoprawny znak w tych ustawieniach regionalnych spowoduje niepowodzenie polecenia.