如何统计文件中A后接XYZ的多行匹配模式(排除A后接A)
问题描述
我有一个文件,内容模式如下:
A . . XYZ . . A . . A . . A . . XYZ
其中.代表内容为随机单词(非A或XYZ)的行。我需要统计所有符合以下模式的出现次数:
A . (任意行数) XYZ
要求仅统计A后直接衔接XYZ的情况,A后接另一个A的情况不计入统计。
我尝试执行以下命令:
pcregrep -Mc 'A.*(\n?|.)*?XYZ' file.txt
但出现报错:
pcregrep: pcre_exec() gave error -27 while matching text that starts:
期望输出为2,请问该如何解决?
解决办法
原因分析
报错的-27是PCRE库的递归深度超限错误,因为你写的正则表达式存在冗余匹配逻辑:.*和(\n?|.)*?会重复匹配内容,导致大量回溯,触发PCRE的递归限制。
正确的pcregrep命令
使用多行模式编写精准的正则,确保只匹配A开头、中间不含A/XYZ的行、最终以XYZ结尾的片段:
pcregrep -Mc 'A(?:\n(?!A|XYZ).*)*\nXYZ' file.txt
正则解析:
A:匹配起始的A行(?:\n(?!A|XYZ).*)*:非捕获组,匹配任意数量的后续行,要求这些行的行首既不是A也不是XYZ(通过负前瞻(?!A|XYZ)判断)\nXYZ:匹配结尾的XYZ行
执行该命令后会输出期望的2。
可选方案:用awk实现(更直观)
如果觉得正则复杂,用awk处理行逻辑更清晰:
awk 'BEGIN{count=0; flag=0} $0 == "A" { flag=1 } flag == 1 { if ($0 == "XYZ") { count++ flag=0 } else if ($0 == "A") { flag=1 # 遇到新的A,重置跟踪,放弃之前的A } } END{print count}' file.txt
逻辑说明:
- 初始化计数器
count和跟踪标志flag - 遇到A时,开启跟踪标志
- 处于跟踪状态时:
- 遇到XYZ则计数器加1,关闭跟踪
- 遇到新的A则重置跟踪(放弃之前的A,因为A后接A不符合要求)
- 最后输出统计结果
内容的提问来源于stack exchange,提问作者Pranav
相关产品推荐
相关产品推荐

