我想使用 bash 查找数组中的重复项及其索引。
例如,我有这个数组:
arr=("a" "b" "c" "a" "c")
在这种情况下,“a”在索引 0 和 3 处重复,“c”也在索引 2 和 4 处重复。
我目前正在使用两个嵌套循环,但我发现它太慢了,尤其是当它是一个大数组时。
在 bash 中是否有更好、更有效的方法来做到这一点?
谢谢你!
答案1
使用 awk,将数组元素作为输入:
$ printf '%s\n' "${arr[@]}" |
awk '{ elmnt[$0]= ($0 in elmnt? elmnt[$0] FS:"") NR-1 }
END{ for (e in elmnt) print e, elmnt[e] }'
a 0 3
b 1
c 2 4
对于新要求(将每个结果保存到 shell 变量中):
$ printf '%s\n' "${arr[@]}" |
awk -v q="'" '{ elmnt[$0]= ($0 in elmnt? elmnt[$0] FS:"") NR-1 }
END{ for (e in elmnt) print e, q elmnt[e] q }' OFS='='
a='0 3'
b='1'
c='2 4'
将以上命令输出保存到文件中,然后使用export varfile
(varfile
只是文件名)导出该文件,因此所有变量都将导出为 shell 变量。
答案2
您可以使用关联数组来检查该值是否已被看到,而不必每次都诉诸线性扫描:
#!/bin/bash
arr=("a" "b" "c" "a" "c")
declare -A values=()
for v in "${arr[@]}"; do
if [ "${values["x$v"]+set}" = set ]; then
echo "value '$v' is duplicate"
break
fi
values["x$v"]=1
done
unset values
与仅转储 awk 处理的值相比,速度有多快可能取决于问题的大小。 shell 速度不快,尤其是 Bash 很慢。