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

StackOverflow https://stackoverflow.com/questions/618378

質問

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

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

tar
gz
java
gz
java
tar
class
class

次のようなリストを見たい:

tar
gz
java
class
役に立ちましたか?

解決

uniq および sort アプリケーションをご覧ください。

./yourscript.ksh | sort | uniq

(FYI、はい、このコマンドラインではソートが必要です。 uniq は、直後にある重複行のみを削除します)

編集:

Aaron Digulla uniq のコマンドラインオプションの関係:

次の入力を与えます:

class
jar
jar
jar
bin
bin
java

uniq はすべての行を一度だけ出力します:

class
jar
bin
java

uniq -d は、2回以上現れるすべての行を出力し、1回印刷します。

jar
bin

uniq -u は、一度だけ表示されるすべての行を出力し、一度だけ出力します。

class
java

他のヒント

./script.sh | sort -u

これは、 monoxideのと同じです答えですが、もう少し簡潔です。

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

./yourscript.ksh | perl -ne 'if (!defined $x{

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

<*>

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

これは&quot; sort | uniq &quot;事前に並べ替えが必要ないという点でソリューション。

}) { print

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

<*>

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

これは&quot; sort | uniq &quot;事前に並べ替えが必要ないという点でソリューション。

; $x{

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

<*>

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

これは&quot; sort | uniq &quot;事前に並べ替えが必要ないという点でソリューション。

} = 1; }'

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

これは&quot; sort | uniq &quot;事前に並べ替えが必要ないという点でソリューション。

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 '!_[<*>]++' infile    
tar
more than one word
gz
java
class

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

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

AWKを使用すると、ソートよりも高速に処理できます

 ./yourscript.ksh | awk '!a[<*>]++'

要求に応じて一意(ただし、並べ替えなし);
〜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[@]}"
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top