Usuń linię, jeśli następny wiersz jest taki sam

15

Jakiego polecenia sed / awk mogę użyć? Po prostu sort -uusunie wszystkie wystąpienia

Wejście:

abc
abc
def
abc
abc
def

Oczekiwany wynik:

abc
def
abc
def
干 猕猴桃
źródło

Odpowiedzi:

36

Do tego uniqsłuży standardowe polecenie.

uniq your-file

Zauważ, że niektóre uniqimplementacje, takie jak GNU uniq, dadzą ci pierwszą z sekwencji wierszy, które sortują to samo (gdzie strcoll()zwraca 0), w przeciwieństwie do identycznych bajtów po bajcie (gdzie memcmp()lub strcmp()zwraca 0). Aby wymusić porównanie bajt-bajt bez względu na uniqimplementację, możesz wymusić ustawienie regionalne za Cpomocą:

LC_ALL=C uniq your-file
Stéphane Chazelas
źródło
7

Vim potrafi to ładnie osiągnąć:

:g/\v^(.*\n)\1/d

Lub jeśli wolisz używać vima jako narzędzia wiersza poleceń, możesz to zrobić jako

vim file -c "g/\v^(.*\n)\1/d" -c "wq"

W ten sposób nie będziesz musiał walczyć z wychodzącym vimem później;)

Wyjaśnienie:

:g/

Na wszystkich liniach, które pasują do tego wyrażenia regularnego ...

\v^(.*\n)\1

Każda linia, po której następuje sama ...

/d

uruchom polecenie d elete (usuń bieżący wiersz). Należy -c "wq"zapisać zmiany i wyjść.

James
źródło
Zauważ, że przynajmniej w vimie 8.1.2112 nie działa on dla zduplikowanych linii, które są dwiema ostatnimi liniami pliku. Ponadto usuwa tylko jeden duplikat z sekwencji 3 duplikatów linii.
Stéphane Chazelas
1
@ StéphaneChazelas z wyjątkiem tego, że obecnie brakuje specyfikacji pożądanego zachowania w przypadku 3-liniowym - mogłem zobaczyć pożądane zachowanie na dwa sposoby.
D. Ben Knoble,