Bash在array1中找到唯一的值,而不是在array2中(反之亦然)



在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

最新更新