找出 array2 中缺少 array1 的哪些值

Find out what values of `array1` are missing in `array2`

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 )

使用 mapfilecommsort 和进程替换:

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 "%s\n" "${array1[@]}" | sort -n) \
                       <(printf "%s\n" "${array2[@]}" | sort -n))

结果:

$ declare -p arr
declare -a arr='([0]="4" [1]="8")'

解释,由内而外:

  • 每行打印数组一个元素并排序:

    $ printf "%s\n" "${array1[@]}" | sort -n
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    

    array2.

  • 也一样
  • 将这些管道包装到进程替换中,并将它们用作 comm:

    的参数
    comm -23 --nocheck-order \
        <(printf "%s\n" "${array1[@]}" | sort -n) \
        <(printf "%s\n" "${array2[@]}" | sort -n)
    

    -23 将结果缩减为第一个数组唯一的值; --nocheck-order 禁止显示有关输入未按字典顺序排序的警告。这个的输出是

    4
    8
    
  • mapfile 将每一行读入数组元素(-t 删除换行符):

    mapfile -t arr < <(comm -23 --nocheck-order \
                       <(printf "%s\n" "${array1[@]}" | sort -n) \
                       <(printf "%s\n" "${array2[@]}" | sort -n))
    

    现在,arr 包含如上所示的两个值。

sort 步骤不是严格要求的,但也使解决方案适用于未排序的数组。

下面的在线人会做这个把戏:

diff -y <(printf '%s\n' "${array2[@]}") <(printf '%s\n' "${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 '%s\n' "${arrayN[@]}"|sort -n)