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

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

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

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

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

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

Ответы [ 10 ]

31 голосов
/ 04 июня 2009

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

uniq filename

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

sort filename | uniq

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

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

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

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

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

3 голосов
/ 04 июня 2009

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

Я признаю, что два вида цитат ужасны.

2 голосов
/ 21 мая 2012

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

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

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

cat filename | uniq > newfilename .

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

2 голосов
/ 04 июня 2009

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

BEGIN { 
     FS=", " 
} 
{ 
    for (i=1; i <= NF; i++) 
        used[$i] = 1
    for (x in used)
        printf "%s, ",x
    printf "\n"
    split("", used)
} 
2 голосов
/ 04 июня 2009

Создать уникальный список довольно просто благодаря 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
1 голос
/ 19 июля 2011

Наткнулся на эту тему при попытке решить практически ту же проблему. Я объединил несколько файлов, содержащих пароли, поэтому, естественно, было много пар. Также много нестандартных персонажей. Я действительно не нуждался в их сортировке, но казалось, что это будет необходимо для 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 `t\203tonnement' and `t\203tonner'

Пробовал:

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 `t\203tonnement' and `t\203tonner'.

И даже попытался сначала пропустить его через 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 `zon\351s' and `zoologie'.

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

Что наконец-то сработало для меня:

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

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

1 голос
/ 04 июня 2009

Я предположил, что вы хотите, чтобы слова были уникальными в одной строке, а не во всем файле. Если это так, то скрипт 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 (){}.

1 голос
/ 04 июня 2009

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

0 голосов
/ 24 мая 2017

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

0 голосов
/ 04 июня 2009

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

...