GNU Awk 5.1.1(Cygwin环境)正则表达式匹配异常及逻辑分支问题排查求助
问题分析与修正方案
让我帮你定位代码里的几个低级错误,这些就是导致你遇到问题的核心原因:
1. gsub 语法完全错误
你写的 gsub(/\x00/, " ", "g"); 存在两处问题:
gsub的第三个参数是要替换的目标字符串,默认是当前行$0,你写的"g"是一个无关的字符串,根本不会修改当前行内容;gsub本身就是全局替换,不需要额外指定"g"参数。
正确写法应该是:
gsub(/\x00/, " "); # 默认替换当前行$0里的所有空字符
2. 错误使用 getline 导致跳过大量行
这是你大部分行没被识别的关键!当你匹配到邮件头行时调用 getline,会强制读取下一行覆盖当前的 $0,然后当前循环结束。而 awk 的默认行为是每次循环自动读取下一行,这就导致你跳过了原本应该处理的行:
- 比如第一次循环处理
Subject:,调用getline后$0变成From:,循环结束; - 第二次循环 awk 自动读取下一行
To:,处理它后再调用getline跳到CC:,循环结束; - 这样
From:、CC:、Date:这些行直接被跳过,根本没进入正常匹配判断,自然落到未匹配分支。
解决方法:直接删掉 getline; 这一行,除非你明确需要手动控制行读取逻辑,否则不要随便用 getline。
3. 正则表达式适配末尾空格
你的测试数据里有些行末尾带有空格(比如 Subject: ),虽然原正则能匹配开头的空格,但为了更严谨,我们可以调整正则,允许关键字冒号后面有任意空格(包括零个):
/^[[:space:]]*(Subject|Date|CC|BCC|From|To):[[:space:]]*$/
这个正则能匹配开头有空格、关键字加冒号、末尾可能带空格的整行内容,完全覆盖你的测试场景。
4. 字符串连接语法错误
你代码里的 $0. "\"" 用了点号,这在 awk 里是错误的——awk 中字符串连接是直接拼接(比如 "abc" "def")或者用逗号分隔输出,点号是用来表示浮点数的。正确写法可以是:
print "Recognized input \"" $0 "\"";
修正后的完整代码
#! /bin/gawk -f { gsub(/\x00/, " "); # 正确替换当前行的空字符为空格 if ($0 ~ /^[[:space:]]+$/) { # 忽略纯空白行 print "Recognized a blank line \"" $0 "\""; } else { if ($0 ~ /^[[:space:]]*(Subject|Date|CC|BCC|From|To):[[:space:]]*$/) { print "Recognized input \"" $0 "\""; } else { print "Did not recognize input \"" $0 "\""; } } }
运行这个修正后的代码,就能得到你期望的输出——所有邮件头行都会被正确识别。
内容的提问来源于stack exchange,提问作者lostbits
相关产品推荐
相关产品推荐

