正则非捕获组匹配异常:如何正确跳过指定内容捕获目标左括号
正则表达式匹配问题求助
当前使用的正则语句
&logline=(?:.*?\[Pipeline\]|\[[\d-]+T[\d:.]+Z\])?.*?(\[)
需求说明
如果字符串里有.*?\[Pipeline\]或者\[[\d-]+T[\d:.]+Z\]这两种内容,就先跳过它们,再捕获后面的左括号[;要是没有这两种内容,就直接捕获字符串里的左括号[。
应匹配的案例
acs&logline=fsdafdsadsdsafdsa sdfs[Pipeline] ++ '[' lucky = as5712 ']'ad&logline= Running on [4AZZVKFkf9ZNK6cEWbpgcClefWPKmoijZvh1OAAA=Docker2_lw in /ws/test_v3_2 :&logline=[2023-09-28T19:39:25.868Z] ++ [[ 1 == \1 ]]afdadsds&logline=[2023-09-28T19:39:25.868Z] ++ [[ ceed_test_runner == \J\O\B\P\O\O\L_\E\N\D_\O\F_\J\O\B\S ]]
不应匹配但被错误匹配的案例
b &logline=[2023-09-28T19:45:09.827Z] Removing yocto/poky/scripts/lib/
问题原因
原正则里的非捕获组用了可选模式?,导致上面的错误案例中,正则直接跳过了非捕获组的匹配,把时间戳开头的[当成目标捕获了。但如果把非捕获组改成必填模式,那些没有[Pipeline]或时间戳的合法案例又会被排除。另外.*?\[Pipeline\]长度不固定,不确定能不能用前瞻/后顾解决,所以来求助。
解决方案
可以用分支匹配+负向预查的思路,明确区分两种场景,同时避开时间戳开头的[。
调整后的正则如下:
&logline=(?:(?:.*?\[Pipeline\]|\[[\d-]+T[\d:.]+Z\]).*?|(?!\[[\d-]+T[\d:.]+Z\]).*?)(\[)
逻辑说明
- 第一个分支
(?:.*?\[Pipeline\]|\[[\d-]+T[\d:.]+Z\]).*?:专门处理有[Pipeline]或时间戳的情况,跳过这些内容后再捕获后续的[ - 第二个分支
(?!\[[\d-]+T[\d:.]+Z\]).*?:处理没有上述两种内容的情况,通过负向预查排除掉以时间戳开头的[,确保只捕获合法的目标左括号
或者更精准的写法,优先匹配并跳过目标前缀:
&logline=(?:.*?(?:\[Pipeline\]|\[[\d-]+T[\d:.]+Z\])|(?!.*?\[[\d-]+T[\d:.]+Z\]).*?)(\[)
这个版本会先找有没有[Pipeline]或时间戳,找到就跳过;找不到的话,再确保不是时间戳开头的字符串,然后捕获里面的[,彻底避免错误匹配时间戳的起始[。
内容的提问来源于stack exchange,提问作者user22009348
相关产品推荐
相关产品推荐

