Python正则表达式负向回顾后发现

3

我们分析由自动化脚本创建的日志。我们通常关注以下一行中的字符串:'1.10.07-SNAPSHOT (1.10.07-20110303.024749-7)'

15:28:02.115 - INFO   - TestLib: Successfully retrieved build version: '1.11.11-SNAPSHOT (1.11.11-20110303.024749-7)'

问题在于,有些日志是手动创建的,用户自己输入这些信息。为了提醒自己格式,他们添加了一个带模板的对话框:

02:24:50.655 - INFO   - gui: Step Dialog: For test results management purposes, specify the build in which the test is executed in the following format, build version: 'specify version here'
02:25:04.905 - INFO   - gui:     Response: OK
02:25:04.905 - INFO   - gui:     Comments: 'build version: '1.11.11''

目前我用的正则表达式是.*[Bb]uild [Vv]ersion:*\s*(?!.*<)'?([^']*)''(?!.*<)'是我为避免这个问题而尝试的第一步,因为有些用户会写“”。但是它不能捕捉上面的情况。我认为正确的做法将是一个负回顾后断言,如果该行中出现'Step Dialog'则不匹配,但是我的尝试似乎让我失败了,根据regexr(由于某种原因,它不让我分享链接到我的保存的表单)。我认为负回顾后断言应该像这样:(?<!Step Dialog)并且结果是这样的:

`(?<!Step Dialog).*[Bb]uild [Vv]ersion:*\s*(?!.*<)'?([^']*)'`

但是由于某种原因,它匹配了上面的第一行和第三行。
编辑: '[Bb]'和':\s'是为那些没有精确使用多个冒号和空格、大写'B'的用户提供的信息。欢迎提出一般性的清理建议,我对正则表达式相对较新。
2个回答

2
你离正确不远了,但是它仍然匹配,因为它可以找到满足.*的字符串,而不需要在Step Dialog之前。正向和负向断言只会影响其周围的模式。因此,你必须强制它检查每个你不想匹配的字符Step Dialog
尝试这个:
`^(?:(?!Step Dialog).)*[Bb]uild [Vv]ersion:*\s*(?!.*<)'?([^']*)'`

现在,它确保位于行首的^[Bb]uild [Vv]ersion之间的每个字符不是Step Dialog字符串。
您会注意到我还将其更改为正向先行查找,因为这样更容易理解正在发生的事情。

1
非常好,非常感谢!我也从中学到了(?:...),这是我之前一直想知道的功能。 - Nathan

0

有几种方法可以做到这一点,但离成功已经很接近了。

`.*(?<!Step Dialog.*)[Bb]uild [Vv]ersion:*\s*(?!.*<)'?([^']*)'`
`^(?!.*Step Dialog).*[Bb]uild [Vv]ersion:*\s*(?!.*<)'?([^']*)'`

Chriszuma的模式也应该可以工作。使用您最喜欢的任何一个。如果性能是一个考虑因素,您可以对这三个模式进行基准测试,看哪个更快。我的感觉是以“.(?)”开头的那个会更快,但我不能确定。

编辑:正如ekhumoro指出的那样,Python正则表达式引擎需要固定长度的向后查找,所以第一个在Python中不起作用。不过第二个应该没问题。


3
第一个模式会导致编译错误,因为反向引用的宽度不是固定的。 - ekhumoro
@ekhumoro - 很好的发现。我忘记了Python不喜欢变宽的后顾。已编辑。 - Justin Morgan
为什么这个被踩了?如果还是不正确,请解释一下原因。 - Justin Morgan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接