2016-06-08 74 views
0
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)找出什么值`array1`中缺少`array2`

+0

@andlrc。谢谢。我不太明白命令替换是什么(但会调查问题)。我改变了第一个正确定义数组。 –

+0

@ Remi.b你这样做的任何理由?这并不是真正的shell脚本。因为这是可能的,但是你有一个特定的目标吗? – andlrc

回答

1

随着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")' 

说明,从内到外:

  • Pr整数阵列每行一个元素和排序:

    $ 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步骤不是严格要求,但也使解决方案也适用于非排序的数组。

+1

您可以使用'printf'%s \ n“”$ {array1 [@]}“'而不是IFS + echo构造。在这个例子中,使用''{{array1 [@]}“'而不是''{{array1 [*]}”'与'printf'变种相关;使用'*'你会得到一个作为参数传递给'printf'的单个字符串。 –

+0

@JonathanLeffler这确实更优雅。 ''{$ array1 [*]}“'''$ {array1 [@]}”'在我的变体中也很重要,顺便说一句,否则'IFS'不用于分隔数组元素 - 只是空间。 –

1

继onliner将这样的伎俩:

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