declare -a array1=( 1 2 3 4 5 6 7 8 9 10 11 12 )
declare -a array2=( 1 2 3 5 6 7 9 10 11 12 )
在 bash 中,如何获取array1
中存在但在array2
中不存在的值的第三个数组?在上面的示例中,预期输出为( 4 8 )
使用 mapfile
、 comm
、 sort
和 process 替换:
array1=( 1 2 3 4 5 6 7 8 9 10 11 12 )
array2=( 1 2 3 5 6 7 9 10 11 12 )
mapfile -t arr < <(comm -23 --nocheck-order
<(printf "%sn" "${array1[@]}" | sort -n)
<(printf "%sn" "${array2[@]}" | sort -n))
结果:
$ declare -p arr
declare -a arr='([0]="4" [1]="8")'
解释,由内而外:
每行打印一个元素的数组并排序:
$ printf "%sn" "${array1[@]}" | sort -n 1 2 3 4 5 6 7 8 9 10 11 12
array2
也是如此.将这些管道包装到进程替换中,并将它们用作
comm
的参数:comm -23 --nocheck-order <(printf "%sn" "${array1[@]}" | sort -n) <(printf "%sn" "${array2[@]}" | sort -n)
-23
将结果简化为第一个数组唯一的值;--nocheck-order
禁止显示有关输入未按字典顺序排序的警告。其输出为4 8
使用
mapfile
将每一行读入数组元素(-t
删除换行符):mapfile -t arr < <(comm -23 --nocheck-order <(printf "%sn" "${array1[@]}" | sort -n) <(printf "%sn" "${array2[@]}" | sort -n))
现在,
arr
包含如上所示的两个值。
sort
步骤不是严格要求的,但使解决方案也适用于未排序的数组。
以下在线者将做到这一点:
diff -y <(printf '%sn' "${array2[@]}") <(printf '%sn' "${array1[@]}") | grep -Po '[|<>][t]K[0-9]+$'
printf
用于在单独的行中打印元素。现在diff -y
给出输出:
1 1
2 2
3 3
5 | 4
6 5
7 6
9 7
10 | 8
11 9
12 10
11
12
现在,您只需过滤|
(有时<
或>
)之后的数字。我为此使用了grep
,但也可以使用sed
。如果您的数组未排序,只需像这样为每个printf
添加排序:
(printf '%sn' "${arrayN[@]}"|sort -n)