回答:
uniq
とsort
アプリケーションを確認することをお勧めします。
./yourscript.ksh | 並べ替え| uniq
(参考までに、このコマンドラインでは並べ替えが必要です。並べ替えは、uniq
直後にある重複する行のみを削除します)
編集:
のコマンドラインオプションに関して、Aaron Digullaが投稿したものとは異なりuniq
ます。
次の入力があるとします。
クラス 瓶 瓶 瓶 置き場 置き場 java
uniq
すべての行を1回だけ出力します。
クラス 瓶 置き場 java
uniq -d
複数回出現するすべての行を出力し、それらを1回出力します。
瓶 置き場
uniq -u
正確に一度だけ現れるすべての行を出力し、それらを一度印刷します:
クラス java
sort
は-u
、独自の値を与えるためのバージョンも備えています。
uniq
縫い目が隣接するラインのみを処理するように(少なくともデフォルトでは)、sort
フィードする前に入力できることを理解しましたuniq
。
... | sort | uniq
ワンショットで実行するよりも効率的だと思います
並べ替えが望ましくない可能性がある大規模なデータセットの場合は、次のperlスクリプトを使用することもできます。
./yourscript.ksh | perl -ne 'if (!defined $x{$_}) { print $_; $x{$_} = 1; }'
これは基本的にすべての行出力を記憶するだけなので、再度出力されません。
sort | uniq
事前に並べ替えが必要ないという点で、「」ソリューションよりも優れています。
zshのあなたはこれを行うことができます。
% cat infile
tar
more than one word
gz
java
gz
java
tar
class
class
zsh-5.0.0[t]% print -l "${(fu)$(<infile)}"
tar
more than one word
gz
java
class
または、AWKを使用できます。
% awk '!_[$0]++' infile
tar
more than one word
gz
java
class
awk
ソリューション(説明については、stackoverflow.com / a / 21200722/45375を参照)は、一意の行の数が十分に小さい限り(一意の行がメモリに保持されている限り)、大きなファイルで動作します。 )。zsh
解決策は、大きなファイルとオプションではないかもしれない、最初にファイル全体をメモリに読み込みます。また、書かれているように、スペースが埋め込まれていない行のみが正しく処理されます。これを修正するには、IFS=$'\n' read -d '' -r -A u <file; print -l ${(u)u}
代わりに使用してください。
(IFS=$'\n' u=($(<infile)); print -l "${(u)u[@]}")
[@]
配列のすべての要素を参照するためにサフィックスがいつ必要かについて興味があります-少なくともバージョン5以降では、それがなくても機能します。それともわかりやすくするために追加しただけですか?
print -l "${(fu)$(<infile)}"
awk
もサンプル出力を修正する自由を取りました。
それらをsort
とを通してパイプしますuniq
。これにより、すべての重複が削除されます。
uniq -d
重複のみをuniq -u
与え、一意のものだけを与えます(重複のストリップ)。
uniq -u
はデフォルトの動作ではありません(詳細については私の回答の編集を参照してください)
要求に応じて一意です(ただし、ソートされません)。
(時間をかけてテストされたように)要素が70未満の場合、システムリソースの使用量が少なくなります。
stdinから入力を受け取るように作成
(または変更して別のスクリプトに含める):(
Bash)
bag2set () {
# Reduce a_bag to a_set.
local -i i j n=${#a_bag[@]}
for ((i=0; i < n; i++)); do
if [[ -n ${a_bag[i]} ]]; then
a_set[i]=${a_bag[i]}
a_bag[i]=$'\0'
for ((j=i+1; j < n; j++)); do
[[ ${a_set[i]} == ${a_bag[j]} ]] && a_bag[j]=$'\0'
done
fi
done
}
declare -a a_bag=() a_set=()
stdin="$(</dev/stdin)"
declare -i i=0
for e in $stdin; do
a_bag[i]=$e
i=$i+1
done
bag2set
echo "${a_set[@]}"