GNU sed 4.9正则表达式合并捕获组后匹配异常问题咨询
正则匹配差异原因分析
核心问题出在正则分组的逻辑错误,第二种写法仅给VV绑定了后缀匹配规则,其他云量代码没有,再加上.*的贪婪匹配特性,导致非VV开头的云量行匹配失败。
两种写法的逻辑对比
第一种正确写法
cat metar.log | sed -nE "s#(.*) EGSH .*(SKC|NCD|CLR|NSC|FEW|SCT|BKN|OVC|TCU|CB|VV)([^ ]*) .*#\1 \2\3#p"
- 逻辑:先匹配任意内容到
EGSH,用.*跳过中间无关内容,然后分两个捕获组:- 捕获所有云量代码(
SKC/OVC/VV等) - 捕获该代码后所有非空格字符(比如
OVC后的001///,VV后的///)
- 捕获所有云量代码(
- 所有云量代码共享后缀匹配规则,不管是纯字母代码(如
SKC)还是带后缀的代码(如OVC001)都能被正确捕获,再通过\2\3合并输出完整云量字段。
第二种错误写法
cat metar.log | sed -nE "s#(.*) EGSH .*(SKC|NCD|CLR|NSC|FEW|SCT|BKN|OVC|TCU|CB|VV[^ ]*) .*#\1 \2#p"
- 逻辑错误:分组内的规则变成要么匹配单个云量代码(如
OVC),要么匹配VV加后缀。 - 贪婪匹配的影响:
.*会尽可能多吞噬字符,以OVC001///为例,.*会把OVC001///全部吞掉直到后面的空格,此时剩余内容里找不到单独的OVC,导致整个正则匹配失败,该行无法输出。 - 仅
VV开头的行能匹配:因为VV[^ ]*可以精准匹配VV///,.*不会吞噬这部分内容,所以能成功输出。
修正后的合并分组写法
要合并捕获组且保证所有行匹配,需给所有云量代码统一加上后缀匹配,正确写法如下:
cat metar.log | sed -nE "s#(.*) EGSH .*((SKC|NCD|CLR|NSC|FEW|SCT|BKN|OVC|TCU|CB|VV)[^ ]*) .*#\1 \2#p"
这里\2直接捕获完整的云量字段(代码+后缀),无需再合并两个分组。
内容的提问来源于stack exchange,提问作者Rufty
相关产品推荐
相关产品推荐

