ImH*_*ere 8 shell bash ksh zsh
什么是减去两个列表的快速方法1。列表可能很小,可能是 shell 工作中的直接方式。或者列表可能很长,也许外部工具是更快的方法。
假设您有两个列表:
list1=( 1 2 3 4 5 6 7 8 9 10 11 12 )
list2=( 1 2 3 5 7 8 9 11 12 )
Run Code Online (Sandbox Code Playgroud)
如何从 list1 中删除 list2 的所有元素以获得listr等效于的结果列表 ( ):
listr=( 4 6 10 )
Run Code Online (Sandbox Code Playgroud)
列表也可以在文件中,如果列表很大(它可能会使用太多内存),则应该如此。
为了使这个问题简短,我将所有算法放在社区答案中。
请阅读那里完成的多项测试。
最初的问题是为了在 list2 中找到完整列表 (list1) 的缺失元素,没有重复。
但是,如果列表是:
list1=( a a b b b c d d )
list2=( b b c c c d d e )
Run Code Online (Sandbox Code Playgroud)
listr= ( a a b )
Run Code Online (Sandbox Code Playgroud)
只有算法 1 和 3 才能正常工作。
算法 2 或 4 都无法做到这一点。
算法 5 (comm) 可以通过执行comm -23.
算法 6 (zsh) 失败。我不知道如何使它工作。
算法 7(通信)。如上所述,使用-23作品。
我还没有分析应该产生的Set 对称差异定义的所有算法:
listr=( a a b c c e )
Run Code Online (Sandbox Code Playgroud)
但是comm -3 list1.txt list2.txt | tr -d ' \t'有效。
1是的,我知道在 shell 中处理文本文件(行列表)是一个坏主意,它的设计速度很慢。
但有些情况似乎无法避免。
我(我们)对建议持开放态度。
Ste*_*itt 11
您可以使用comm删除两个列表共有的任何内容:
listr=($(comm -3 <(printf "%s\n" "${list1[@]}" | sort) <(printf "%s\n" "${list2[@]}" | sort) | sort -n))
Run Code Online (Sandbox Code Playgroud)
这将按comm期望的顺序对两个列表进行排序,比较它们,仅输出对任一列表唯一的项目,然后按数字顺序再次对它们进行排序。
如果两个列表都按字典顺序排序(按LC_COLLATE),则可以避免再次排序:
listr=($(comm --nocheck-order -3 <(printf "%s\n" "${list1[@]}") <(printf "%s\n" "${list2[@]}")))
Run Code Online (Sandbox Code Playgroud)
如果您需要比较的值存储在文件中,这也很有效。
#!/bin/zsh
list1=( 1 2 3 4 5 6 7 8 9 10 11 12 )
list2=( 1 2 3 5 7 8 9 11 12 )
listr=("${(@)list1:|list2}")
typeset -p listr
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6366 次 |
| 最近记录: |