如何在bash中删除现有数组中的重复元素?

Joh*_*gus 4 unix bash

如何创建仅包含 Array 中存在的唯一元素的 newArray?

例如:ARRAY 分别包含aa ab bb aa ab ccARRAY[0-5] 处的元素。

当我打印 newARRAY 时,我只想要aa ab bb cc分别在 newARRAY[0-3] 处。

我已经搜索堆栈溢出一段时间了,但没有解决我的问题。我试图做newARRAY=$(ARRAY[@] | sort -u | uniq,但重复的元素仍然存在。

Joh*_*024 8

天真的方法

要获取唯一元素arr并假设没有元素包含换行符:

$ printf "%s\n" "${arr[@]}" | sort -u
aa
ab
bb
cc
Run Code Online (Sandbox Code Playgroud)

更好的方法

要获得一个 NUL 分隔的列表,即使有换行符也能正常工作:

$ printf "%s\0" "${arr[@]}" | sort -uz
aaabbbcc
Run Code Online (Sandbox Code Playgroud)

(当然,这在终端上看起来很难看,因为它不显示 NUL。)

把这一切放在一起

要在 中捕获结果newArr

$ newArr=(); while IFS= read -r -d '' x; do newArr+=("$x"); done < <(printf "%s\0" "${arr[@]}" | sort -uz)
Run Code Online (Sandbox Code Playgroud)

运行上面的代码后,我们可以使用declare来验证这newArr是我们想要的数组:

$ declare -p newArr
declare -a newArr=([0]="aa" [1]="ab" [2]="bb" [3]="cc")
Run Code Online (Sandbox Code Playgroud)

对于那些喜欢将代码分散在多行上的人,上面可以重写为:

newArr=()
while IFS= read -r -d '' x
do
    newArr+=("$x")
done < <(printf "%s\0" "${arr[@]}" | sort -uz)
Run Code Online (Sandbox Code Playgroud)

补充说明

不要对变量名称使用全部大写。系统和外壳程序的名称全部使用大写字母,您不想意外地覆盖其中之一。


jhn*_*hnc 5

您可以使用关联数组来跟踪您所看到的元素:

#!/bin/bash

ARRAY=(aa ab bb aa ab cc)

unset dupes # ensure it's empty
declare -A dupes

for i in "${ARRAY[@]}"; do
    if [[ -z ${dupes[$i]} ]]; then
        NEWARRAY+=("$i")
    fi
    dupes["$i"]=1
done
unset dupes # optional

printf "[%s]" "${ARRAY[@]}"
echo
printf "[%s]" "${NEWARRAY[@]}"
echo
Run Code Online (Sandbox Code Playgroud)