在bash中,我知道可以通过以下方式找到两个数组之间的唯一值:
echo "${array1[@]} ${array2[@]}" | tr ' ' 'n' | sort | uniq -u
然而,这给出了两个数组之间的唯一值。如果我想对array1唯一的元素和array2唯一的元素怎么办?例如:
array1=(1 2 3 4 5)
array2=(2 3 4 5 6)
original_command_output = 1 6
new_command_output1 = 1
new_command_output2 = 6
您可以使用comm
命令
获取第一个数组的唯一元素:
comm -23
<(printf '%sn' "${array1[@]}" | sort)
<(printf '%sn' "${array2[@]}" | sort)
和第二个数组的唯一元素:
comm -13
<(printf '%sn' "${array1[@]}" | sort)
<(printf '%sn' "${array2[@]}" | sort)
或者,更健壮的,允许任何字符包括换行符作为元素的一部分,在空字节上分割:
comm -z -23
<(printf '%s ' "${array1[@]}" | sort -z)
<(printf '%s ' "${array2[@]}" | sort -z)
comm
可能是一种方法,但如果你运行的是bash>= 4,那么你可以使用关联数组:
#!/bin/bash
declare -a array1=(1 2 3 4 5) array2=(2 3 4 5 6)
declare -A uniq1=() uniq2=()
for e in "${array1[@]}"; do uniq1[$e]=; done
for e in "${array2[@]}"; do
if [[ ${uniq1[$e]-1} ]]
then
uniq2[$e]=
else
unset "uniq1[$e]"
fi
done
echo "new_command_output1 = ${!uniq1[*]}"
echo "new_command_output2 = ${!uniq2[*]}"
new_command_output1 = 1
new_command_output2 = 6
BASH内置程序可以更干净、更快地处理这个问题。这将读取每个元素的两个数组,比较它们是否存在于其中一个数组中。如果没有找到匹配项,则输出唯一元素
arr1=(1 2 3 4 5)
arr2=(1 3 2 4)
for i in "${arr1[@]}" "${arr2[@]}" ; do
[[ ${arr2[@]} =~ $i ]] || echo $i
[[ ${arr1[@]} =~ $i ]] || echo $i
done
输出:5
如果你的一个数组有多个字符元素,例如152,那么你必须转换数组,在前后添加一个文字字符。这样,regex就可以识别一个精确匹配的
arr1=(1 2 3 4 5)
arr2=(1 3 2 4 152)
for i in "${arr1[@]}" ; do
var1+="^$i$"
done
for i in "${arr2[@]}" ; do
var2+="^$i$"
done
for i in "${arr1[@]}" "${arr2[@]}" ; do
[[ $var1 =~ "^$i$" ]] || echo $i
[[ $var2 =~ "^$i$" ]] || echo $i
done
输出:5 152