Bash如何分别查找两个数组中各自独有的元素
Bash 分别获取两个数组独有元素的实现方案
你原本使用的命令是取两个数组的对称差集,也就是两边互不共有的所有元素合集。如果需要分别提取仅在第一个数组存在、仅在第二个数组存在的元素,优先使用系统自带的comm命令实现,逻辑清晰且性能更好。
核心实现逻辑
comm是专门用于对比两个已排序文本流的命令,默认输出3列内容:
- 第1列:仅在第一个输入流中存在的行
- 第2列:仅在第二个输入流中存在的行
- 第3列:两个输入流共有的行
通过参数可以指定屏蔽不需要的列,直接拿到目标差集:
-23:屏蔽第2、3列,只输出仅第一个输入有的内容(即仅array1存在的元素)-13:屏蔽第1、3列,只输出仅第二个输入有的内容(即仅array2存在的元素)
可直接运行的示例
对应你给出的测试数组,完整代码如下:
array1=(1 2 3 4 5) array2=(2 3 4 5 6) # 提取仅在array1中存在的元素 only_in_array1=($(comm -23 \ <(printf "%s\n" "${array1[@]}" | sort) \ <(printf "%s\n" "${array2[@]}" | sort) \ )) # 提取仅在array2中存在的元素 only_in_array2=($(comm -13 \ <(printf "%s\n" "${array1[@]}" | sort) \ <(printf "%s\n" "${array2[@]}" | sort) \ )) # 验证输出 echo "仅array1独有元素:${only_in_array1[@]}" # 输出:1 echo "仅array2独有元素:${only_in_array2[@]}" # 输出:6
代码里用<(...)是Bash原生的进程替换语法,会把括号内命令的输出作为临时文件传给comm,不需要手动创建临时文件;用printf "%s\n"代替echo | tr是为了避免特殊字符、转义符导致的输出异常。
兼容特殊元素的写法
如果你的数组元素本身包含空格、换行、特殊符号,用下面的写法可以避免元素被错误拆分:
IFS=$'\n' only_in_array1=($(comm -23 <(printf "%s\n" "${array1[@]}" | sort) <(printf "%s\n" "${array2[@]}" | sort))) IFS=$'\n' only_in_array2=($(comm -13 <(printf "%s\n" "${array1[@]}" | sort) <(printf "%s\n" "${array2[@]}" | sort))) unset IFS
备选方案(无comm环境时使用)
如果运行环境没有comm命令,也可以用grep实现差集匹配,注意加-F参数按固定字符串匹配、-x参数匹配整行,避免正则特殊字符、子串匹配导致的错误:
# 仅array1存在的元素 only_in_array1=($(printf "%s\n" "${array1[@]}" | grep -Fxvf <(printf "%s\n" "${array2[@]}"))) # 仅array2存在的元素 only_in_array2=($(printf "%s\n" "${array2[@]}" | grep -Fxvf <(printf "%s\n" "${array1[@]}")))
这个方案性能比comm差,数组元素较多时优先用comm方案。
内容的提问来源于stack exchange,提问作者Miss_Orchid
相关产品推荐
相关产品推荐

