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

17

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

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 ответов

28

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

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