Как удалить повторяющиеся слова из текстового файла с помощью команды linux
У меня есть текстовый файл со словами, разделенными запятой, например:
word1, word2, word3, word2, word4, word5, word 3, word6, word7, word3
Я хочу удалить дубликаты и стать:
word1, word2, word3, word4, word5, word6, word7
Любые идеи? Я думаю, egrep может мне помочь, но я не уверен, как использовать его точно.
Ответы
Ответ 1
Предполагая, что слова по одному на строку, и файл уже отсортирован:
uniq filename
Если файл не отсортирован:
sort filename | uniq
Если они не по одному в строке, и вы не возражаете против того, чтобы они были по одному в строке:
tr -s [:space:] \\n < filename | sort | uniq
Это не устраняет пунктуацию, поэтому, возможно, вы хотите:
tr -s [:space:][:punct:] \\n < filename | sort | uniq
Но это удаляет дефис из переносимых слов. "man tr" для дополнительных параметров.
Ответ 2
ruby -pi.bak -e '$_.split(",").uniq.join(",")' filename
?
Я признаю, что два вида цитат уродливы.
Ответ 3
Создание уникального списка довольно легко благодаря 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
Ответ 4
Здесь awk script, который оставит каждую строку в такте, только удаляя повторяющиеся слова:
BEGIN {
FS=", "
}
{
for (i=1; i <= NF; i++)
used[$i] = 1
for (x in used)
printf "%s, ",x
printf "\n"
split("", used)
}
Ответ 5
У меня была та же самая проблема сегодня.. список слов с 238 000 слов, но около 40 000 из них были дубликатами. Я уже имел их в отдельных строках, делая
cat filename | tr " " "\n" | sort
чтобы удалить дубликаты, я просто сделал
cat filename | uniq > newfilename .
Не работает без ошибок, и теперь мой файл с 1,45 МБ до 1,01 МБ
Ответ 6
Я бы подумал, что вы захотите заменить пробелы новыми символами, используйте команду uniq, чтобы найти уникальные строки, затем замените новые строки пробелами.
Ответ 7
Я предположил, что вы хотите, чтобы слова были уникальными в одной строке, а не во всем файле. Если это так, то Perl script ниже выполнит трюк.
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 (){}
.
Ответ 8
Пришел к этому потоку, пытаясь решить ту же проблему. Я объединил несколько файлов, содержащих пароли, поэтому, естественно, было много парных. Кроме того, многие нестандартные символы. Мне они действительно не нужны, но казалось, что это будет необходимо для 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
Он также сохранил слова, единственное различие которых было случайным, что я и хотел. Мне не нужен список, отсортированный, так что было хорошо, что это не так.
Ответ 9
И не забудьте параметр -c
для утилиты uniq
, если вы заинтересованы в получении количества слов.
Ответ 10
открыть файл с помощью vim (vim filename
) и запустить команду сортировки с уникальным флагом (:sort u
).