如何编写Bash脚本读取文件按ID分组查找并输出重复记录
解决方案
现有脚本问题
你原来的脚本存在两个核心问题:
- 没有按
NEXT分隔的分组处理数据,每次触发判断都会对整个文件做全局去重,完全不符合分组统计的要求 - 没有过滤分组内的注释行、空行,也没有提取对应分组的身份号前缀
实现思路
直接用awk处理效率远高于纯bash循环,适合千条以上的批量数据,逻辑如下:
- 以
NEXT作为分组边界,每碰到NEXT就重置上一个分组的统计数据 - 每个分组内优先读取身份号前缀,过滤掉以
#开头的注释行和空行 - 统计每个
displayName行的出现次数,同时保留原始行的顺序(避免排序打乱重复行的展示) - 分组处理完成后如果存在重复记录,就按要求的格式输出
可用脚本
你可以直接用下面的bash脚本,替换你原来的内容即可:
#!/bin/bash INPUT="sourceFile.txt" awk ' # 碰到NEXT就处理上一个分组,然后重置变量 /^NEXT$/{ # 先处理上一个分组的重复数据 if(id != "" && has_dup){ print "NEXT" print id for(i=0;i<line_cnt;i++){ cnt = line_count[all_lines[i]] if(cnt >=2){ # 重复多少次就打印多少次 for(j=0;j<cnt;j++){ print all_lines[i] } # 避免重复打印同一行的重复记录 delete line_count[all_lines[i]] } } print "\nEND OF ONE ID-NUMBER IN FILE\n" } # 重置分组变量 id = "" line_cnt = 0 delete line_count delete all_lines has_dup = 0 next } # 跳过空行和注释行 /^$|^#/{next} # 第一个非空非注释行是身份号前缀 id == ""{ id = $0 next } # 剩下的都是displayName行,统计次数并存储 { line_count[$0]++ all_lines[line_cnt++] = $0 if(line_count[$0] >=2) has_dup = 1 } # 处理最后一个分组 END{ if(id != "" && has_dup){ print "NEXT" print id for(i=0;i<line_cnt;i++){ cnt = line_count[all_lines[i]] if(cnt >=2){ for(j=0;j<cnt;j++){ print all_lines[i] } delete line_count[all_lines[i]] } } print "\nEND OF ONE ID-NUMBER IN FILE\n" } } ' "$INPUT"
效果验证
用你提供的示例输入文件运行上述脚本,输出结果和要求的期望格式完全一致。
内容的提问来源于stack exchange,提问作者Asquared
相关产品推荐
相关产品推荐

