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



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



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


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



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


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

639   10  

10 ответов:

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

uniq filename

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

sort filename | uniq

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

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

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

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

, но что удаляет дефис со словами, написанными через дефис. "man tr" для большего количества вариантов.

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

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

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

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

BEGIN { 
     FS=", " 
} 
{ 
    for (i=1; i <= NF; i++) 
        used[$i] = 1
    for (x in used)
        printf "%s, ",x
    printf "\n"
    split("", used)
} 

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

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

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

cat filename | uniq > newfilename .

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

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

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

Наткнулся на этот поток, пытаясь решить во многом ту же проблему. Я объединил несколько файлов, содержащих пароли, поэтому, естественно, было много двойников. Также много нестандартных персонажей. На самом деле мне не нужно было их сортировать, но, похоже, это было необходимо для 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 /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
Он также сохранил слова, единственным отличием которых был падеж, чего я и добивался. Мне не нужно было сортировать список, так что это было прекрасно, что его не было.

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

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

Comments

    Ничего не найдено.