如何在Bash中统计多个纯文本文件的独有行数?
用Bash实现多文件独有行提取方案
当然有靠谱的Bash实现方式啦!针对你要找出每个文件相对于其他所有文件的独有行的需求,我整理了两种实用方法,直接就能套用~
方法一:sort + comm组合(新手友好,逻辑直观)
comm命令天生用来对比两个有序文件的差异,但它只能处理两个文件。咱们可以通过把当前文件之外的所有文件合并去重,再和当前文件对比,就能轻松拿到独有行。
具体命令
# 替换成你的目标文件列表,比如 file1 file2 file3 target_files="file1 file2 file3" for file in $target_files; do # 合并当前文件之外的所有文件,排序并去重 other_content=$(cat $target_files | grep -v "^$file$" | sort -u) # 对比当前文件(先排序)和合并后的其他文件,提取独有行 unique_lines=$(sort "$file" | comm -23 - <(echo "$other_content")) # 按要求格式输出 echo "$file:" echo "$unique_lines" done
关键步骤解释
cat $target_files | grep -v "^$file$":排除当前循环的文件,合并其他所有文件的内容sort -u:合并后去重,避免其他文件里的重复行干扰对比结果comm -23:只保留第一个文件(当前文件)独有的行(-23表示排除第二个文件共有的行)<(echo "$other_content"):把字符串转成伪文件,让comm能正常处理
你的示例运行效果
针对你给出的file1、file2、file3,运行后会输出:
file1: 3 file2: 50 file3: 40 6 100
方法二:awk高效处理(大文件/多文件场景首选)
如果你的文件数量多或者体积大,方法一的多次排序会有点慢。用awk只需要遍历所有文件一次,效率提升明显。核心思路是记录每行在哪些文件中出现过,最后筛选出只在单个文件出现的行。
具体命令
awk ' { # 记录每行出现的文件名,用逗号分隔 line_files[$0] = (line_files[$0] ? line_files[$0] "," : "") FILENAME # 保存每个文件的所有行(自动去重同一个文件内的重复行) file_lines[FILENAME][$0] = 1 } END { # 遍历每个目标文件 for (filename in file_lines) { printf "%s:\n", filename # 遍历该文件的每一行 for (line in file_lines[filename]) { # 拆分该行对应的文件列表 split(line_files[line], files, ",") # 如果只有一个文件且就是当前文件,输出该行 if (length(files) == 1 && files[1] == filename) { print line } } } } ' file1 file2 file3
逻辑说明
- 第一部分:遍历所有文件的每一行,用
line_files[$0]存储该行出现过的所有文件名;用file_lines[FILENAME][$0]记录每个文件包含的行(自动去重同文件内的重复行) - END部分:遍历每个文件,检查它的每一行对应的文件列表,如果长度为1且就是当前文件,说明这行是独有行,直接输出
可选调整
如果你需要保留原文件内的重复行(比如file1里有两个1,且1只在file1出现,要输出两个1),可以把代码里的file_lines[FILENAME][$0] = 1改成file_lines[FILENAME][++cnt[FILENAME]] = $0,并调整后续遍历逻辑,就能按原顺序输出所有重复的独有行。
内容的提问来源于stack exchange,提问作者Cpt_Pi
相关产品推荐
相关产品推荐

