web-dev-qa-db-ja.com

UNIXシェルスクリプトのリストから一意または個別の値を選択します

改行で区切られた値の長いリストを返すkshスクリプトがあり、一意/個別の値のみを表示したい。これを行うことは可能ですか?

たとえば、出力がディレクトリ内のファイルサフィックスであるとします。

tar
gz
Java
gz
Java
tar
class
class

私は次のようなリストを見たいです:

tar
gz
Java
class
197
brabster

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 
363
./script.sh | sort -u

これは 一酸化物answer と同じですが、もう少し簡潔です。

74
gpojd

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
9

それらをsortおよびuniqにパイプします。これにより、すべての重複が削除されます。

uniq -dは重複のみを提供し、uniq -uは一意のもののみを提供します(重複を削除します)。

9
Aaron Digulla

並べ替えが望ましくない可能性がある大きなデータセットの場合は、次のPerlスクリプトも使用できます。

./yourscript.ksh | Perl -ne 'if (!defined $x{$_}) { print $_; $x{$_} = 1; }'

これは基本的にすべての行出力を記憶するだけなので、再び出力されることはありません。

sort | uniq」ソリューションに勝る利点は、事前にソートが必要ないことです。

9
paxdiablo

AWKでできることは、並べ替えよりも速いことです

 ./yourscript.ksh | awk '!a[$0]++'
6
Ajak6

要求に応じて一意(ただし、並べ替えなし)。
使用するシステムリソースの数が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[@]}"
1
FGrose