Bash中用AWK遍历文件列检测值一致性 遇不匹配停止输出前序列
解决方案
你可以直接使用以下awk脚本实现需求,无需生成临时文件,处理效率远高于shell循环方案:
awk ' # 中小文件版本(无需二次读取文件) { # 把所有行存入数组缓存 lines[NR] = $0 # 第一行记录每列的基准值 if (NR == 1) { for (i = 1; i <= NF; i++) base[i] = $i max_valid_col = NF next } # 逐行校验列一致性 for (i = 1; i <= max_valid_col; i++) { if ($i != base[i]) { max_valid_col = i - 1 break } } # 提前终止条件:没有有效列直接停止处理 if (max_valid_col == 0) break } END { # 输出所有行的有效列 for (n = 1; n <= NR; n++) { split(lines[n], fields) for (i = 1; i <= max_valid_col; i++) { printf "%s%s", fields[i], i == max_valid_col ? "\n" : " " } } } ' 你的输入文件.txt
如果是GB级超大文件,不想占用内存缓存所有行,可以使用二次读取版本:
awk ' # 大文件版本(低内存占用) NR == 1 { for (i = 1; i <= NF; i++) base[i] = $i max_valid_col = NF next } { for (i = 1; i <= max_valid_col; i++) { if ($i != base[i]) { max_valid_col = i - 1 break } } if (max_valid_col == 0) exit } END { while ((getline line < ARGV[1]) > 0) { split(line, fields) for (i = 1; i <= max_valid_col; i++) { printf "%s%s", fields[i], i == max_valid_col ? "\n" : " " } } } ' 你的输入文件.txt
实现逻辑
- 读取第一行时,把每列的值存为基准值,初始默认所有列都是有效列
- 从第二行开始逐行校验,从第一列开始对比是否和基准值一致,一旦碰到不一致的列,立刻记录最大有效列为当前列的前一列,停止后续列的校验
- 所有行处理完成后,逐行输出前
max_valid_col列的内容
和你原有思路的对比
你原本的shell循环思路存在两个明显问题:
- 每检查一列都要遍历一次整个文件,列数多、文件大时性能会非常差
- 需要生成临时文件,额外增加IO开销,异常场景下还可能产生垃圾文件
上述awk方案仅需1-2次遍历即可完成处理,无额外开销,适配任意大小的输入文件。
内容的提问来源于stack exchange,提问作者user95146
相关产品推荐
相关产品推荐

