Answers:
使用GNU awk
(这也会保留原始顺序)
printf '%s\n' "1 2 3 2 1" | awk -v RS='[[:space:]]+' '!a[$0]++{printf "%s%s", $0, RT}'
1 2 3
要read
成bash
数组
read -ra arr<<<$(printf '%s\n' "1 2 3 2 1" |
awk -v RS='[[:space:]]+' '!a[$0]++{printf "%s%s", $0, RT}')
printf "%s\n" "${arr[@]}"
1
2
3
bash
数组,则添加了一种方法
如果您使用的是zsh:
$ array=(1 2 3 2 1)
$ echo ${(u)array[@]}
1 2 3
或(如果KSH_ARRAYS
未设置选项)甚至
$ echo ${(u)array}
1 2 3
"${(u)array[@]}"
或"${(@u)array}"
代替(请注意引号)。
${(u)array}
即使该数组为空或包含空字符串(不带引号)也可以使用。
对于具有任意值的数组,使用它非常棘手,bash
因为它没有内置的运算符。
bash
但是碰巧不支持在变量中存储NUL字符,因此您可以利用该字符将其传递给其他命令:
等同于zsh
:
new_array=("${(@u}array}")
在最新的GNU系统上,可能是:
eval "new_array=($(
printf "%s\0" "${array[@]}" |
LC_ALL=C sort -zu |
xargs -r0 bash -c 'printf "%q\n" "$@"' sh
))"
另外,对于的最新版本bash
,并假设所有数组元素都不为空,则可以使用关联数组:
unset hash
typeset -A hash
for i in "${array[@]}"; do
hash[$i]=
done
new_array=("${!hash[@]}")
使用bash 4.4和更高版本以及GNU sort
:
readarray -td '' new_array < <(
printf '%s\0' "${array[@]}" | LC_ALL=C sort -zu)
在这些不同的解决方案中,元素的顺序将不同。
与tcsh
:
set -f new_array = ($array:q)
将保留˚F IRST元件(a b a
=> a b
)等zsh
的(u)
扩展标志位。
set -l new_array = ($array:q)
将保留最后一个(a b a
=> b a
)。但是那些从数组中删除了空元素。
这个解决方案对我有用。
ids=(1 2 3 2 1)
echo "${ids[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '
上面产生1 2 3作为输出。
如Costas所建议的,较短的版本可能是
printf "%s\n" "${ids[@]}" | sort -u | tr '\n' ' '
要将最终结果存储到数组中,您可以执行以下操作:
IFS=$' '
arr=($(printf "%s\n" "${ids[@]}" | sort -u | tr '\n' ' '))
unset IFS
现在,当我对进行回显时arr
,这就是我得到的输出。
echo "${arr[@]}"
1 2 3
参考文献
https://stackoverflow.com/a/13648438/1742825 https://stackoverflow.com/a/9449633/1742825
tr '\n' ' '
要完全在外壳中完成并将结果放入数组中,
declare -A seen
for word in one two three two one
do
if [ ! "${seen[$word]}" ]
then
result+=("$word")
seen[$word]=1
fi
done
echo "${result[@]}"
换句话说:如果还没有看到给定的单词,请将其添加到result
数组中并将其标记为已看到。一旦看到一个单词,就忽略它的后续出现。
unset seen
之前已定义(即使是环境中的标量变量),则需要先declare -A seen
进行准备$seen
。