Удаление повторяющихся строк в vi?

124

У меня есть текстовый файл, содержащий длинный список записей (по одной в каждой строке). Некоторые из них являются дубликатами, и я хотел бы знать, можно ли (и если да, то как) удалить любые дубликаты. Мне интересно сделать это из vi / vim, если это возможно.

Sydius
источник
1
Похоже на дубликат stackoverflow.com/questions/746689/…
Натан Феллман,
4
Этому 1 год; это 10 месяцев. Итак, наоборот.
Сидиус,
Консенсус @Sydius теперь заключается в том, чтобы установить приоритет подсчета голосов (которого у вас также больше): meta.stackexchange.com/questions/147643/… И это не дубликаты, в нем не упоминается Vim :-)
Сиро Сантилли 郝海东 冠状 病六四 事件 法轮功 08

Ответы:

271

Если вы согласны с сортировкой файла, вы можете использовать:

:sort u
Брайан Карпер
источник
6
Это так красиво. Спасибо!
Shrayas
8
Если сортировка недопустима, используйте, :%!uniqчтобы просто удалить повторяющиеся записи без сортировки файла.
cryptic0 06
как только вы используете команду, весь файл изменяется? как ты вернешься? Я уже по ошибке сохранил файл ... мой плохой
nilon
Просто используйте команду отмены Vim :u
adampasz
25

Попробуй это:

:%s/^\(.*\)\(\n\1\)\+$/\1/

Он ищет любую строку, за которой сразу следует одна или несколько собственных копий, и заменяет ее одной копией.

Сделайте копию своего файла, прежде чем попробовать. Это не проверено.

Шон
источник
1
@hop Спасибо за тестирование. В то время у меня не было доступа к vim.
Шон,
2
это выделяет все повторяющиеся строки для меня, но не удаляет, я пропустил шаг здесь?
ak85
Я уверен, что это также выделит строку, за которой следует строка с таким же префиксом, но более длинная.
hippietrail
3
Единственная проблема с этим заключается в том, что если у вас есть несколько дубликатов (3 или более одинаковых строк), вам придется запускать это много раз, пока все дубли не исчезнут, поскольку это удаляет только один набор дубликатов за раз.
horta
2
Еще один недостаток: это не сработает, если ваши повторяющиеся строки уже находятся рядом друг с другом. Сортировка в первую очередь будет одним из способов убедиться, что они рядом друг с другом. В этом случае другие ответы, вероятно, будут лучше.
Орта
23

Из командной строки просто выполните:

sort file | uniq > file.new
Kevin
источник
1
Это мне очень пригодилось для огромного файла. Спасибо!
Rafid
1
Не удалось заставить принятый ответ работать, так как :sort uон висел в моем большом файле. Это сработало очень быстро и идеально. Спасибо!
Tgsmith61591
1
'uniq' is not recognized as an internal or external command, operable program or batch file.
hippietrail
1
Да, я пробовал эту технику с файлом размером 2,3 ГБ, и это было потрясающе быстро.
DanM
@hippietrail Вы используете ПК с windows? Может быть, вы можете использовать cygwin.
12431234123412341234123
8

awk '!x[$0]++' yourfile.txtесли вы хотите сохранить порядок (т. е. сортировка недопустима). Чтобы вызвать его из vim, :!можно использовать.

Ровин Бхандари
источник
4
Это прекрасно! Отсутствие необходимости в сортировке - это именно то , что я искал!
Cometsong
6
g/^\(.*\)$\n\1/d

У меня работает в Windows. Однако сначала необходимо отсортировать строки.

Bridgey
источник
1
Это приведет к удалению строки, следующей за строкой, которая является его префиксом: с aaaaпоследующим ошибочным aaaabbудалением aaaa.
hippietrail
5

Я бы совмещал два из приведенных выше ответов:

go to head of file
sort the whole file
remove duplicate entries with uniq

1G
!Gsort
1G
!Guniq

Если вам было интересно узнать, сколько повторяющихся строк было удалено, используйте control-G до и после, чтобы проверить количество строк, присутствующих в вашем буфере.

Джон ДеллОро
источник
1
'uniq' is not recognized as an internal or external command, operable program or batch file.
hippietrail
3

Затем выберите линии в режиме визуальных линий ( Shift+ v) :!uniq. Это будет ловить только дубликаты, которые идут один за другим.

derobert
источник
1
Просто чтобы отметить это будет только работать на компьютерах с Uniq программы установлены т.е. Linux, Mac, FreeBSD и т.д.
anteatersa
Это будет лучший ответ для тех, кому не нужна сортировка. А если вы пользователь Windows, попробуйте Cygwin или MSYS.
fx-kirin
1

Что касается того, как Uniq может быть реализован в VimL, ​​ищите Uniq в плагине, который я поддерживаю . Вы увидите различные способы его реализации, указанные в списке рассылки Vim.

В противном случае :sort uэто действительно путь.

Люк Эрмитт
источник
0
:%s/^\(.*\)\(\n\1\)\+$/\1/gec

или

:%s/^\(.*\)\(\n\1\)\+$/\1/ge

это мой ответ для вас, он может удалить несколько повторяющихся строк и сохранить только одну!

cn8341
источник
0

Я бы использовал !}uniq, но это работает, только если нет пустых строк.

Для каждой строки в файле используйте: :1,$!uniq.

Крис Додд
источник
0

Эта версия удаляет только повторяющиеся строки, которые совпадают. Я имею в виду, удаляет только последовательные повторяющиеся строки. При использовании данной карты функция не замечает беспорядка с пустыми строками. Но если изменить REGEX, чтобы он соответствовал началу строки, ^он также удалит повторяющиеся пустые строки.

" function to delete duplicate lines
function! DelDuplicatedLines()
    while getline(".") == getline(line(".") - 1)
        exec 'norm! ddk'
    endwhile
    while getline(".") == getline(line(".") + 1)
        exec 'norm! dd'
    endwhile
endfunction
nnoremap <Leader>d :g/./call DelDuplicatedLines()<CR>
SergioAraujo
источник
0

Альтернативный метод, который не использует vi / vim (для очень больших файлов), - это из командной строки Linux использовать sort и uniq:

sort {file-name} | uniq -u
уилльям-1066
источник
0

Это сработало для меня как для, так .csvи для.txt

awk '!seen[$0]++' <filename> > <newFileName>

Объяснение: Первая часть команды печатает уникальные строки, а вторая часть, т.е. после средней стрелки, предназначена для сохранения вывода первой части.

awk '!seen[$0]++' <filename>

>

<newFileName>

Павел
источник