bash从列表中删除重复的字符串

时间:2016-06-22 07:59:11

标签: string bash grep

我想从String中删除重复的字符串。例如:

A="Dog Cat Horse Dog Dog Cat"

字符串A应如下所示:

A="Dog Cat Horse"

如何为此编写Shell脚本?

4 个答案:

答案 0 :(得分:2)

如果顺序不重要,您可以使用关联数组:

declare -A uniq
for k in $A ; do uniq[$k]=1 ; done
echo ${!uniq[@]}

答案 1 :(得分:1)

  1. (安全地)将字符串拆分为空白,创建一个包含每个单词的数组:

    read -r -d '' -a words < <(printf '%s\0' "$A")
    
  2. 循环数组的字段,将字存储到关联数组中;如果已经看到这个词,请忽略它

    declare -A Aseen
    Aunique=()
    for w in "${words[@]}"; do
        [[ ${Aseen[$w]} ]] && continue
        Aunique+=( "$w" )
        Aseen[$w]=x
    done
    
  3. 您可以将Aunique数组打印到标准输出:

    printf '%s\n' "${Aunique[@]}"
    

    产生:

    Dog
    Cat
    Horse
    

    或用它创建一个新的字符串

    Anew="${Aunique[*]}"
    printf '%s\n' "$Anew"
    

    产生:

    Dog Cat Horse
    

    或使用分隔符加入数组,例如,使用字符,

    IFS=, eval 'Asep="${Aunique[*]}"'
    printf '%s\n' "${Asep[@]}"
    

    产生:

    Dog,Cat,Horse
    
  4. 所有这些都使用Bash≥4功能。如果您仍然坚持使用较旧的Bash版本,那么有一些解决方法,但它不会安全,美观和轻松......

    注意。此方法不会对字符串进行排序:单词保留原始顺序,仅删除重复项。

    这是在空格字符上拆分字符串的规范(和安全!)方式(或者更常见的是在特殊变量IFS中包含的字符,它具有默认值值空间 - 标签 - 换行符)。不要使用像words=( $A )这样的恐怖:它会受到文件名扩展(globbing)的影响。广泛遇到的另一种方法是read -r -a words <<< "$A";这很好(即安全),但不会处理A中的换行符。

    这里使用eval是100%安全的(因为单引号);它实际上是在Bash中连接数组元素的规范方法(或加入POSIX shell中的位置参数)。

答案 2 :(得分:0)

你可以使用这个,

echo "a a b b c c" | tr ' ' '\n' | sort | uniq | tr '\n' ' ' | sed -e 's/[[:space:]]*$//'

答案 3 :(得分:0)

gawk:

 awk -v RS="[ \n]" -v ORS=" " '!($0 in a){print;a[$0]}' <(echo $A)