我有一个ksh脚本,它返回一个长列表的值,换行符分隔,我想只看到唯一的/不同的值。这是可能的吗?

例如,我的输出是一个目录下的文件后缀:

焦油 广州 java 广州 java 焦油 类 类

我想看到这样的列表:

焦油 广州 java 类


当前回答

对于较大的数据集,排序可能是不可取的,你也可以使用以下perl脚本:

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

它基本上只记住每一行输出,这样就不会再次输出。

与“sort | uniq”解决方案相比,它的优势在于不需要预先进行排序。

其他回答

./script.sh | sort -u

这和一氧化碳的答案是一样的,但是更简洁一点。

通过sort和uniq对它们进行管道处理。这将删除所有重复项。

Uniq -d只给出重复项,Uniq -u只给出唯一项(条带重复项)。

用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你可以做到:

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

我发现它比sort和uniq快

唯一的,按照请求,(但没有排序); 对少于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[@]}"