DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

awk 加入 getline 后跳过记录,末尾重复旧值

getline 额外消费主输入,正常规则不会再次处理该记录;按逐行或两行分组需求重写,并区分 EOF 与读取错误。

输入有三行,awk 动作里加入 getline next_line 后,某一行没有进入正常规则,最后还重复打印了前一行的内容。这通常是把 getline 当成了“不移动输入位置的预览”:它实际上会消费下一条记录。

下面限定 GNU awk(命令名 gawk),使用默认换行记录分隔符、单个普通文本输入文件,不启用输入重试扩展。多行记录格式需要按实际 RS 判断,不能一律按物理行计数。

多读一次,主循环就少见一条记录

假设 ./records.txt 内容如下:

alpha
beta
gamma

这段是问题写法,只读文件并输出文本:

gawk '{ getline next_line; print next_line; print $0 }' ./records.txt

预期输出顺序是 beta、alpha、beta、gamma,而不是依次查看三个位置的“下一行”。

第一次执行动作时,主循环已经读到 alpha,它保存在 $0。getline next_line 从同一主输入再读走 beta,把它赋给变量,但不改当前 $0。动作结束后,主循环继续取得的记录便是 gamma;beta 不会再单独进入整套规则。

第二次执行动作时已经没有下一条记录,getline 返回 0。继续无条件打印 next_line,就会输出上次读到的旧值。要判断是否获得新记录,应检查返回状态,不能靠变量是否为空:空行也是一次成功读取。

NR、FNR 在成功读入主输入记录时增加,是读取结果的计数,不是控制文件当前位置的索引。把 NR 减一不会把已经消费的记录放回去。

只需要逐行处理时,去掉多余的 getline

如果每行都应经过同样的处理,直接使用 awk 自带的主循环:

gawk '{ print NR, $0 }' ./records.txt

样例预期得到 1 alpha、2 beta、3 gamma。把实际处理表达式放进这个动作即可,不需要先写一层 while (getline ...)。额外读取的记录不会从第一条规则重新开始;后面还有其他模式和动作时,这种遗漏更容易被隐藏。

需要相邻两行比较时,可以保留上一条记录,等主循环读到当前记录再比较。例如:

gawk '
    NR > 1 { print previous, $0 }
    { previous = $0 }
' ./records.txt

这里只输出 alpha beta 和 beta gamma,最后一条没有虚构的后继。它表达的是相邻记录配对,不是交换两行;应先明确业务要求,不能把两种输出混用。

确实按两行一组时,区分成功、末尾和错误

如果目标就是交换每一对相邻行,才需要主动取走第二条。下面保留奇数条输入的最后一条,并在读取错误时返回非零状态:

gawk '
{
    result = (getline next_line)
    if (result == 1) {
        print next_line
        print $0
    } else if (result == 0) {
        print $0
    } else {
        print "getline failed: " ERRNO > "/dev/stderr"
        exit 1
    }
}' ./records.txt

样例预期输出 beta、alpha、gamma。普通 GNU awk 输入中,1 表示读到记录,0 表示输入结束,负数表示错误。不能写成 if (getline next_line) 就认为只有成功才进入分支,因为负数在条件中也是真。

这段只处理一个文件。把多个文件直接加到命令后面,主输入会按文件继续读取,可能把前一文件的末行与下一文件的首行配成一对;各文件必须独立配对时,应分别处理或另行设计文件边界逻辑。

getline next_line 不重新切分字段,当前 $0、$1 等字段和 NF 保持原记录。去掉变量改成裸 getline 则会替换当前记录并更新字段,不能作为等价修复。

用奇数条输入检查末尾处理

验证至少包括空文件、一条、两条、三条记录以及空行。逐行处理应没有漏项;两行交换应保留奇数末行,而且读取失败不能被当作正常结束。空行应按记录参与处理,不应因内容为空被跳过。

以上命令只向标准输出写结果。真正保存转换结果时,使用单独的新输出位置并检查命令状态,不要重定向覆盖输入文件。发生读取错误时,已输出的前缀不代表完整结果,应丢弃候选输出并保留原文件。上线前保存原脚本和输入;回退恢复原版本,不能靠调整计数器补回已经漏处理的业务记录。