Как удалить дубликаты слов из простого текстового файла с помощью команды linux

18

У меня есть простой текстовый файл со словами, разделенными запятой, например:

word1, word2, word3, word2, word4, word5, word 3, word6, word7, word3

я хочу удалить дубликаты и стать:

word1, word2, word3, word4, word5, word6, word7

Есть идеи? Я думаю, egrep может помочь мне, но я не уверен, как именно его использовать ....

    
задан cupakob 04.06.2009 в 20:24
источник
  • Вы хотите, чтобы слова были уникальными на основе строк или над всем файлом? Также вы хотите сохранить исходный порядок слов, или вы счастливы, если заказ изменен? –  Beano 04.06.2009 в 20:46
  • Мне нужны слова uniq во всем файле. порядок слов не важен. –  cupakob 04.06.2009 в 21:15
  • См. также: Как найти повторяющиеся слова в файле с помощью grep / egrep? –  Martin Thoma 12.01.2017 в 12:13

10 ответов

29

Предполагая, что слова по одному в строке, и файл уже отсортирован:

uniq filename

Если файл не отсортирован:

sort filename | uniq

Если они не по одному на строку, и вы не против, чтобы они были по одному на строку:

tr -s [:space:] \n < filename | sort | uniq

Это не удаляет пунктуацию, поэтому, может быть, вы захотите:

tr -s [:space:][:punct:] \n < filename | sort | uniq

Но это удаляет дефис из переносимых слов. «man tr» для дополнительных параметров.

    
ответ дан Randy Orrison 04.06.2009 в 20:30
  • , который работает для меня :) Большое спасибо ... Мне нужно всего лишь вернуть все слова в одну строку: cat testfile_out.txt | tr "\ n" ""> testfile_out2.txt –  cupakob 04.06.2009 в 21:24
  • «sort -u» устранит необходимость в uniq –  Beano 04.06.2009 в 21:38
3

ruby -pi.bak -e '$_.split(",").uniq.join(",")' filename ?

Я признаю, что два вида цитат безобразны.

    
ответ дан Oliver N. 04.06.2009 в 20:33
  • Ruby не является командой Linux! Я предполагаю, что команда Linux означает регулярные программы GNU. –  Danny 04.06.2009 в 20:52
  • @ Danny, я видел это, и вы могли бы сделать это с некоторой чрезмерной alchemy sed / awk, но на самом деле я думаю, что это работа для языка сценариев. –  Oliver N. 04.06.2009 в 21:16
  • ___ qstntxt ___ <div class="post-text" itemprop="text"> <p> У меня есть текстовый файл со словами, разделенными запятой, например: </p> %pre% <p> Я хочу удалить дубликаты и стать: </p> %pre% <p> Любые идеи? Я думаю, egrep может мне помочь, но я не уверен, как использовать его точно. </P>     </DIV> ___ answer952293 ___ <div class="post-text" itemprop="text"> <p> Предполагая, что слова по одному на строку, и файл уже отсортирован: </p> %pre% <p> Если файл не отсортирован: </p> %pre% <p> Если они не по одному в строке, и вы не возражаете против того, чтобы они были по одному в строке: </p> %pre% <p> Это не устраняет пунктуацию, поэтому, возможно, вы хотите: </p> %pre% <p> Но это удаляет дефис из переносимых слов. «man tr» для дополнительных параметров. </p>     </DIV> ___ answer952314 ___ <div class="post-text" itemprop="text"> <p> %code% ? </p> <p> Я признаю, что два вида цитат уродливы. </p>     </DIV> ___ qstnhdr ___ Как удалить повторяющиеся слова из текстового файла с помощью команды linux ___ answer952501 ___ <div class="post-text" itemprop="text"> <p> Вот скрипт awk, который оставит каждую строку в такте, только удаляя повторяющиеся слова: </p> %pre%     </DIV> ___ answer10686186 ___ <div class="post-text" itemprop="text"> <p> У меня была та же самая проблема сегодня .. список слов с 238 000 слов, но около 40 000 из них были дубликатами. Я уже имел их в отдельных строках, делая </p> %pre% <p>, чтобы удалить дубликаты, я просто сделал </p> %pre% <p> Не работает без ошибок, и теперь мой файл с 1,45 МБ до 1,01 МБ </p>     </DIV> ___ answer952374 ___ <div class="post-text" itemprop="text"> <p> Я предположил, что вы хотите, чтобы слова были уникальными в одной строке, а не во всем файле. Если это так, то скрипт Perl ниже выполнит трюк. </P> %pre% <p> Если вы хотите уникальность по всему файлу, вы можете просто переместить хэш %code% вне цикла %code% . </p>     </DIV> ___ answer952406 ___ <div class="post-text" itemprop="text"> <p> Создание уникального списка довольно легко благодаря %code% , хотя большинство команд Unix, как и одна запись в строке, вместо списка с разделителями-запятыми, поэтому мы должны начать с преобразования его в это: </p> %pre% <p> Чем сложнее повторить это на одной строке с запятыми как разделители, а не терминаторы. Я использовал perl one-liner для этого, но если у кого-то есть что-то более идиоматическое, пожалуйста, отредактируйте меня. :) </Р> %pre%     </DIV> ___ answer952429 ___ <div class="post-text" itemprop="text"> <p> И не забудьте параметр %code% для утилиты %code% , если вы заинтересованы в получении количества слов. </p>     </DIV> ___ answer6741093 ___ <div class="post-text" itemprop="text"> <p> Пришел к этому потоку, пытаясь решить ту же проблему. Я объединил несколько файлов, содержащих пароли, поэтому, естественно, было много парных. Кроме того, многие нестандартные символы. Мне они действительно не нужны, но казалось, что это будет необходимо для uniq. </P> <p> Я пробовал: </p> %pre% <p> Пробовал: </p> %pre% <p> И даже попробовал сначала пропустить его через кошку, так что я мог убедиться, что мы получаем правильный ввод. </p> %pre% <p> Я не уверен, что происходит. Строки «t \ 203tonnement» и «t \ 203tonner» не найдены в файле, хотя найдены «t / 203» и «tonnement», но на отдельных соседних строках. То же самое с «zon \ 351s». </P> <p> Что, наконец, помогло мне: </p> %pre% <p> Он также сохранил слова, единственное различие которых было случайным, что я и хотел. Мне не нужен список, отсортированный, так что было хорошо, что это не так. </P>     </DIV> ___ answer952291 ___ <div class="post-text" itemprop="text"> <p> Я бы подумал, что вы захотите заменить пробелы новыми символами, используйте команду <a href="http://www.computerhope.com/unix/uuniq.htm"> uniq </a>, чтобы найти уникальные строки, затем снова замените строки новой строки пробелами. </p>     </DIV> ___ commmment760725 ___ Мне нужны слова uniq во всем файле. порядок слов не важен. ___ commmment760603 ___ Вы хотите, чтобы слова были уникальными на основе строк или над всем файлом? Также вы хотите сохранить исходный порядок слов, или вы счастливы, если заказ изменен? ___ commmment760843 ___ «sort -u» устранит необходимость в uniq ___ commmment760784 ___, который работает для меня :) Большое спасибо ... Мне нужно всего лишь вернуть все слова в одну строку: cat testfile_out.txt | tr "\ n" ""> testfile_out2.txt ___ commmment760631 ___ Ruby не является командой Linux! Я предполагаю, что команда Linux означает регулярные программы GNU. ___ answer44151793 ___ <div class="post-text" itemprop="text"> <p> открыть файл с помощью vim ( %code% ) и запустить команду сортировки с уникальным флагом ( %code% ). </p>     </DIV> ___ commmment760729 ___ @ Danny, я видел это, и вы могли бы сделать это с некоторой чрезмерной alchemy sed / awk, но на самом деле я думаю, что это работа для языка сценариев. ___ ___ commmment760935 +1, как это кажется неоспоримо элегантным и более доступным для смертных по сравнению с Perl однострочника Игоря Krivokon в :) ___ commmment760881 ___, и это также работает ___ commmment760667 ___ tr "" "\ n" может быть более эффективным, чем sed в этом случае ___ commmment761408 ___ Положить это на одну строку довольно просто: sed 's /, / \ n / g' filename | сортировать | paste -s -d, | sed 's /, /, / g' команда - паста, очень хорошая! ___ commmment760589 ___ он будет в сочетании с сортировкой ___ commmment760548 ___ uniq сравнивает только смежные строки, поэтому это не сработает. ___ commmment761995 ___ 'tr "" "\ n"' отличается тем, что он не обрабатывает запятые, и вы не можете просто игнорировать запятые, потому что последнее слово их не имеет. С примером в этом вопросе вы получите uniq'ing «word3» и «word3». Другой ответ имеет команду tr, которая удалит все пробелы и все знаки пунктуации, если это то, что вам нужно. Я просто был конкретным. ___ commmment760636 ___ Perl не является командой Linux! Я предполагаю, что команда Linux означает регулярные программы GNU. Затем снова Perl устанавливается везде ... хе. ___ commmment760839 ___, который также работает, но не идеален;) вывод содержит слово с двумя запятыми .... это не большая проблема :) большое спасибо ___ commmment8908741 ___ +1 для вашего кода. Нужен один лайнер для «уникальной» последовательности строк. Благодаря!! ___ commmment760711 ___ Я имею в виду команду, которая интегрирована в установку по умолчанию самых популярных дистрибутивов ... например, sometink like grep. ___ commmment760685 ___ Не могли бы вы указать, что означает ваше определение «команды Linux» (или, скорее, @ rbright, как вы, кажется, знаете его)? Может быть, команда найдена в дистрибутивах Linux? ___ commmment70424700 ___ См. также: Как найти повторяющиеся слова в файле с помощью grep / egrep? ___ –  Jonik 04.06.2009 в 21:54
2

Создать уникальный список довольно просто благодаря uniq , хотя большинство команд Unix, например, одна запись в строке вместо списка, разделенного запятыми, поэтому мы должны начать с преобразования его в следующий:

$ sed 's/, /\n/g' filename | sort | uniq
word1
word2
word3
word4
word5
word6
word7

Более сложная задача - снова поместить это в одну строку с запятыми в качестве разделителей, а не терминаторов. Я использовал perl one-liner для этого, но если у кого-то есть что-то более идиоматическое, пожалуйста, отредактируйте меня. :)

$ sed 's/, /\n/g' filename | sort | uniq | perl -e '@a = <>; chomp @a; print((join ", ", @a), "\n")'
word1, word2, word3, word4, word5, word6, word7
    
ответ дан Ryan Bright 04.06.2009 в 20:49
  • tr "" "\ n" может быть более эффективным, чем sed в этом случае –  florin 04.06.2009 в 21:03
  • , и это также работает –  cupakob 04.06.2009 в 21:44
  • Положить это на одну строку довольно просто: sed 's /, / \ n / g' filename | сортировать | paste -s -d, | sed 's /, /, / g' команда - паста, очень хорошая! –  Mapio 04.06.2009 в 23:21
  • 'tr "" "\ n"' отличается тем, что он не обрабатывает запятые, и вы не можете просто игнорировать запятые, потому что последнее слово их не имеет. С примером в этом вопросе вы получите uniq'ing «word3» и «word3». Другой ответ имеет команду tr, которая удалит все пробелы и все знаки пунктуации, если это то, что вам нужно. Я просто был конкретным. –  Ryan Bright 05.06.2009 в 01:52
2

Вот сценарий awk, который оставляет такт в каждой строке, удаляя только повторяющиеся слова:

BEGIN { 
     FS=", " 
} 
{ 
    for (i=1; i <= NF; i++) 
        used[$i] = 1
    for (x in used)
        printf "%s, ",x
    printf "\n"
    split("", used)
} 
    
ответ дан mamboking 04.06.2009 в 21:09
  • , который также работает, но не идеален;) вывод содержит слово с двумя запятыми .... это не большая проблема :) большое спасибо –  cupakob 04.06.2009 в 21:37
2

У меня была та же самая проблема сегодня ... список слов с 238 000 слов, но около 40 000 из них были дубликатами. Я уже имел их в отдельных строках, делая

cat filename | tr " " "\n" | sort 

чтобы удалить дубликаты, которые я просто сделал

cat filename | uniq > newfilename .

Сработало без ошибок, и теперь мой файл уменьшен с 1,45 МБ до 1,01 МБ.

    
ответ дан Biffinum 21.05.2012 в 15:28
1

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

    
ответ дан Paul Sonier 04.06.2009 в 20:29
  • uniq сравнивает только смежные строки, поэтому это не сработает. –  Beano 04.06.2009 в 20:33
  • он будет в сочетании с сортировкой –  Jonik 04.06.2009 в 20:43
1

Я предположил, что вы хотите, чтобы слова были уникальными в одной строке, а не во всем файле. Если это так, то приведенный ниже скрипт Perl поможет.

while (<DATA>)
{
    chomp;
    my %seen = ();
    my @words = split(m!,\s*!);
    @words = grep { $seen{$_} ? 0 : ($seen{$_} = 1) } @words;
    print join(", ", @words), "\n";
}

__DATA__
word1, word2, word3, word2, word4, word5, word3, word6, word7, word3

Если вам нужна уникальность всего файла, вы можете просто переместить хеш %seen за пределы цикла while (){} .

    
ответ дан Beano 04.06.2009 в 20:45
  • Perl не является командой Linux! Я предполагаю, что команда Linux означает регулярные программы GNU. Затем снова Perl устанавливается везде ... хе. –  Danny 04.06.2009 в 20:53
  • Не могли бы вы указать, что означает ваше определение «команды Linux» (или, скорее, @ rbright, как вы, кажется, знаете его)? Может быть, команда найдена в дистрибутивах Linux? –  Beano 04.06.2009 в 21:08
  • Я имею в виду команду, которая интегрирована в установку по умолчанию самых популярных дистрибутивов ... например, sometink like grep. –  cupakob 04.06.2009 в 21:13
  • +1 для вашего кода. Нужен один лайнер для «уникальной» последовательности строк. Благодаря!! –  GuruM 11.09.2011 в 17:31
1

Наткнулся на эту тему, пытаясь решить практически ту же проблему. Я объединил несколько файлов, содержащих пароли, поэтому, естественно, было много пар. Также много нестандартных персонажей. Я действительно не нуждался в их сортировке, но казалось, что это будет необходимо для Uniq.

Я пытался:

sort /Users/me/Documents/file.txt | uniq -u
sort: string comparison failed: Illegal byte sequence
sort: Set LC_ALL='C' to work around the problem.
sort: The strings compared were 't3tonnement' and 't3tonner'

Пробовал:

sort -u /Users/me/Documents/file.txt >> /Users/me/Documents/file2.txt
sort: string comparison failed: Illegal byte sequence
sort: Set LC_ALL='C' to work around the problem.
sort: The strings compared were 't3tonnement' and 't3tonner'.

И даже попытался сначала пропустить его через cat, чтобы я мог видеть, получали ли мы правильные данные.

cat /Users/me/Documents/file.txt | sort | uniq -u > /Users/me/Documents/file2.txt
sort: string comparison failed: Illegal byte sequence
sort: Set LC_ALL='C' to work around the problem.
sort: The strings compared were 'zon1s' and 'zoologie'.

Я не уверен, что происходит. Строки "t \ 203tonnement" и "t \ 203tonner" не найдены в файле, хотя "t / 203" и "tonnement" найдены, но на отдельных несмежных строках. То же самое с "zon \ 351s".

Что в итоге сработало для меня:

awk '!x[$0]++' /Users/me/Documents/file.txt > /Users/me/Documents/file2.txt

Здесь также сохранились слова, единственное отличие которых было в случае, что я и хотел. Мне не нужно было сортировать список, поэтому было прекрасно, что это не так.

    
ответ дан sudon't 19.07.2011 в 02:39
0

И не забудьте опцию -c для утилиты uniq , если вы также заинтересованы в подсчете количества слов.

    
ответ дан Rob Wells 04.06.2009 в 20:54
0

откройте файл с помощью vim ( vim filename ) и выполните команду сортировки с уникальным флагом ( :sort u ).

    
ответ дан meysam 24.05.2017 в 09:30