基于第一列提取第三列值为0的连续区间首尾行(孤立行重复输出)
问题描述
原始输入文件
1 1 1 1 2 5 1 3 0 1 4 0 1 5 0 1 6 3 1 7 4 1 8 0 1 9 0 2 1 0 2 2 0 2 3 1 2 4 0 3 1 1 3 2 1 3 3 2
需求说明
- 提取第三列值为0的连续行的首行与末行;
- 若某行第三列为0且前后无同值行,需重复输出该行;
- 按第一列分组处理:当第一列值变化时,即使第三列仍为0,也需视为新的0值区间。
期望输出
1 3 0 1 5 0 1 8 0 1 9 0 2 1 0 2 2 0 2 4 0 2 4 0
当前使用的awk脚本
awk ' function print_prev() { if (prevline) print prevline prevline="" } $3!=0 { print_prev() } $3==0 { if (prev3!=$3) print prevline=$0 } { prev3=$3 } END { print_prev() } ' test.txt
当前脚本输出
1 3 0 1 5 0 1 8 0 2 2 0 2 4 0 2 4 0
当前脚本未处理第一列分组逻辑,导致跨分组的0区间被错误合并,比如1 8 0到2 2 0被当成一个区间,未按分组拆分为两个独立区间输出首尾行。
修正后的awk脚本
awk ' # 输出当前0区间的首尾行,单一行则重复输出 function print_zero_range() { if (in_zero) { print startline # 首尾同一行则重复输出 if (startline == currline) { print currline } else { print currline } in_zero = 0 } } # 触发区间结束的情况:当前行第三列非0,或者第一列与上一行不同且处于0区间 $3 != 0 || ($1 != prev1 && in_zero) { print_zero_range() } # 处理0值行 $3 == 0 { # 若当前不在0区间,记录起始行 if (!in_zero) { startline = $0 in_zero = 1 } # 更新当前行(区间末行) currline = $0 } # 记录上一行的第一列值 { prev1 = $1 } # 处理文件末尾剩余的0区间 END { print_zero_range() } ' test.txt
修正说明
- 新增
prev1变量跟踪上一行的第一列值,用于判断分组变化; - 用
in_zero标记是否处于0值区间,startline记录区间首行,currline记录区间当前行(即末行); - 当遇到非0值行,或者第一列变化且当前处于0区间时,调用
print_zero_range输出区间首尾; - 单一行的0区间会重复输出该行,满足需求;
- END块确保文件末尾的0区间被处理。
修正后输出
1 3 0 1 5 0 1 8 0 1 9 0 2 1 0 2 2 0 2 4 0 2 4 0
内容的提问来源于stack exchange,提问作者pedro
相关产品推荐
相关产品推荐

