改行で区切られた値の長いリストを返すkshスクリプトがあり、一意/個別の値のみを表示したい。これを行うことは可能ですか?
たとえば、出力がディレクトリ内のファイルサフィックスであるとします。
tar gz Java gz Java tar class class
私は次のようなリストを見たいです:
tar gz Java class
uniq
およびsort
アプリケーションをご覧ください。
./ yourscript.ksh |並べ替え| uniq
(FYI、はい、このコマンドラインではソートが必要です。uniq
は、直後にある重複行のみを削除します)
編集:
uniq
のコマンドラインオプションに関連して Aaron Digulla によって投稿されたものに反して:
次の入力が与えられた場合:
クラス jar jar jar bin bin Java
uniq
は、すべての行を1回だけ出力します。
クラス jar bin Java
uniq -d
は、複数回出現するすべての行を出力し、それらを1回出力します。
jar bin
uniq -u
は、一度だけ現れるすべての行を出力し、一度だけ出力します:
クラス Java
zshでこれを行うことができます:
zsh-5.0.0[t]% 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を使用できます。
zsh-4.3.9[t]% awk '!_[$0]++' infile
tar
more than one Word
gz
Java
class
それらをsort
およびuniq
にパイプします。これにより、すべての重複が削除されます。
uniq -d
は重複のみを提供し、uniq -u
は一意のもののみを提供します(重複を削除します)。
並べ替えが望ましくない可能性がある大きなデータセットの場合は、次のPerlスクリプトも使用できます。
./yourscript.ksh | Perl -ne 'if (!defined $x{$_}) { print $_; $x{$_} = 1; }'
これは基本的にすべての行出力を記憶するだけなので、再び出力されることはありません。
「sort | uniq
」ソリューションに勝る利点は、事前にソートが必要ないことです。
AWKでできることは、並べ替えよりも速いことです
./yourscript.ksh | awk '!a[$0]++'
要求に応じて一意(ただし、並べ替えなし)。
使用するシステムリソースの数が70個未満の場合(時間をかけてテストした場合)。
stdinから入力を取得するように記述された、
(または変更して別のスクリプトに含める):
(バッシュ)
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[@]}"