我想从String中删除重复的字符串。例如:
A="Dog Cat Horse Dog Dog Cat"
字符串A应如下所示:
A="Dog Cat Horse"
如何为此编写Shell脚本?
答案 0 :(得分:2)
如果顺序不重要,您可以使用关联数组:
declare -A uniq
for k in $A ; do uniq[$k]=1 ; done
echo ${!uniq[@]}
答案 1 :(得分:1)
(安全地)将字符串拆分为空白,创建一个包含每个单词的数组:†
read -r -d '' -a words < <(printf '%s\0' "$A")
循环数组的字段,将字存储到关联数组中;如果已经看到这个词,请忽略它
declare -A Aseen
Aunique=()
for w in "${words[@]}"; do
[[ ${Aseen[$w]} ]] && continue
Aunique+=( "$w" )
Aseen[$w]=x
done
您可以将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
所有这些都使用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)