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`
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`
随着mapfile
,comm
,sort
和工艺替代:
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
步骤不是严格要求,但也使解决方案也适用于非排序的数组。
您可以使用'printf'%s \ n“”$ {array1 [@]}“'而不是IFS + echo构造。在这个例子中,使用''{{array1 [@]}“'而不是''{{array1 [*]}”'与'printf'变种相关;使用'*'你会得到一个作为参数传递给'printf'的单个字符串。 –
@JonathanLeffler这确实更优雅。 ''{$ array1 [*]}“'''$ {array1 [@]}”'在我的变体中也很重要,顺便说一句,否则'IFS'不用于分隔数组元素 - 只是空间。 –
继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)
@andlrc。谢谢。我不太明白命令替换是什么(但会调查问题)。我改变了第一个正确定义数组。 –
@ Remi.b你这样做的任何理由?这并不是真正的shell脚本。因为这是可能的,但是你有一个特定的目标吗? – andlrc