PCRE2转POSIX ERE无惰性匹配致结果异常,如何调整正则?
POSIX ERE正则适配:正确提取版本号
原PCRE2正则及效果
我原本使用的PCRE2正则如下:
^project\(.+?version\s*:\s*'(.+?)'.*\)$
该正则的第一个捕获组可以从以下文本中提取出0.9.20:
project( 'waybar', 'cpp', 'c', version: '0.9.20', license: 'MIT', meson_version: '>= 0.50.0', default_options : [ 'cpp_std=c++20', 'buildtype=release', 'default_library=static' ], )
适配POSIX ERE遇到的问题
我尝试将其转换为POSIX扩展正则表达式(ERE),写出了如下正则:
^project\([^)]*version[[:space:]]*:[[:space:]]*'([^']*)'.*\)$
但实际捕获组匹配到的是>= 0.50.0而非目标的0.9.20。原因是[^)]*会匹配所有非)的字符,而POSIX ERE不支持惰性匹配(?),导致匹配直接延伸到了meson_version所在行,最终捕获了最后一个符合'[^']*'格式的内容。
解决方案
要解决这个问题,需要限制project(到第一个version之间的匹配范围,避免跳过目标version去匹配后续的meson_version。可以使用否定预查来实现类似惰性匹配的效果,修正后的POSIX ERE正则如下:
^project\((?:(?!version)[^)])*version[[:space:]]*:[[:space:]]*'([^']+)'.*\)$
正则说明:
^project\(:匹配文本开头的project((?:(?!version)[^)])*:关键部分——匹配任意非)的字符,但每匹配一个字符前都会检查后面是否是version,如果是则停止匹配,精准停在第一个version之前,避免过度匹配到后续的meson_versionversion[[:space:]]*:[[:space:]]*'([^']+)':匹配version: 'xxx'格式的内容,并捕获引号内的版本号([^']+匹配所有非引号的字符,确保只捕获当前引号内的内容).*\)$:匹配剩余内容直到文本结尾的)
这个正则可以正确从目标文本中捕获0.9.20,不会误匹配到meson_version的内容。
内容的提问来源于stack exchange,提问作者Jacob Birkett
相关产品推荐
相关产品推荐

