たとえば、コンマで区切られた単語を含むプレーンテキストファイルがあります。
Word1, Word2, Word3, Word2, Word4, Word5, Word 3, Word6, Word7, Word3
重複を削除して次のようになりたい:
Word1, Word2, Word3, Word4, Word5, Word6, Word7
何か案は? egrepが役立つと思いますが、正確に使用する方法はわかりません。
単語が1行に1つあり、ファイルがすでにソートされていると仮定します。
uniq filename
ファイルがソートされていない場合:
sort filename | uniq
1行に1つではなく、1行に1つでも構わない場合:
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
?
2種類の引用は醜いと認めます。
一意のリストの作成はuniq
のおかげで非常に簡単ですが、ほとんどのUnixコマンドは、コンマ区切りのリストではなく、1行に1つのエントリを入力するので、まず次のように変換する必要があります。
$ sed 's/, /\n/g' filename | sort | uniq
Word1
Word2
Word3
Word4
Word5
Word6
Word7
難しいのは、これを改行記号としてターミネーターではなくコンマを付けて1行に配置することです。私はこれを行うためにPerlワンライナーを使用しましたが、誰かがもっと慣用的なものを持っている場合は、私を編集してください。 :)
$ 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語の単語リストですが、そのうちの約4万語が重複しています。私はすでに個別のラインでそれらを持っていました
cat filename | tr " " "\n" | sort
重複を削除するために、私は単にしました
cat filename | uniq > newfilename .
エラーはまったく発生せず、ファイルは1.45MBから1.01MBに減少しました
ファイル全体ではなく、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 (){}
ループの外に移動するだけです。
ほぼ同じ問題を解決しようとしているときに、このスレッドに出くわしました。私はパスワードを含むいくつかのファイルを連結したので、当然のことながら多くのダブルスがありました。また、多くの非標準文字。私は本当にそれらをソートする必要はありませんでしたが、それは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
また、大文字小文字のみが異なる単語も保存されました。リストを並べ替える必要がなかったので、並べ替えなくても問題ありませんでした。
スペースを改行に置き換え、 niq コマンドを使用して一意の行を検索し、改行をスペースに再度置き換えたいと思います。
また、単語の数も取得したい場合は、uniq
ユーティリティの-c
オプションを忘れないでください。
vim(vim filename
)と一意のフラグ(:sort u
)。