在 Bash 中查找数组中的重复项及其索引

在 Bash 中查找数组中的重复项及其索引

我想使用 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 varfilevarfile只是文件名)导出该文件,因此所有变量都将导出为 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 很慢。

相关内容