0

我正在尝试编写一些正则表达式来解析 Hyperic HQ 生成的警报中的信息。警报以电子邮件的形式出现,主题行如下:

"[HQ] !!! - Alert: My Demo Website Alert Resource: demo.myserver.net Apache Web Server State: fixed"

长话短说,我需要能够始终如一地获取“Ap​​ache Web 服务器”部分,而不管主机名可能甚至不存在。我知道主机名总是以“myserver.net”结尾。

我拥有的正则表达式是:

/Resource:\s.*(?<=mydomain.net)?\s(.*)\s(?=State)/

我期望这将匹配 and 之间的零个或多个字符"Resource:""State:"可选地跟随(但不包括)主机名。

不幸的是,它返回的是"Server",即我要匹配的位的最后一个字。无论主机名是否在字符串中,都会发生这种情况。

任何人都可以帮忙吗?

编辑:下面乍得提供的解决方案

/Resource:\s(?:.*.myserver.net)?(.*)\sState/ 
4

3 回答 3

3

这是我称之为Premature Recourse to Lookaround的反模式示例。您知道您要查找的字符串之前foo和之后是bar,并且您知道正则表达式具有称为lookbehinds 和lookaheads 的东西,所以很明显这就是您应该使用的:

(?<=foo).*(?=bar)

当心显而易见的;很少有关于正则表达式是直观的。请记住,前瞻是对正则表达式的一个相当晚的补充,而后瞻甚至更晚,但人们早在他们出现之前就已经解决了这类问题。他们通过使用捕获组来做到这一点,在大多数情况下这仍然是最好的选择:

foo(.*)bar

您的正则表达式中还有一个彻底的错误:后面的?量词:

(?<=mydomain.net)?

EditPadPro 的搜索框将其标记为错误,PHP 也是如此;Java 和 .NET 没有,但我相信他们应该这样做。它不比\b*or ^+or更有意义${3,7}。这些都是零宽度断言,这意味着它们不匹配任何内容,因此通过添加量词,您试图多次匹配相同的内容(请记住,$不匹配换行符,只是换行符和前一个字符之间的位置)。

没有陷入无限循环的危险,但这很好地表明正则表达式的作者犯了错字或误解了某些东西。当量词是可以匹配零次的量词时尤其如此,例如?or *。它使断言成为可选的,而可选的断言是不相关的断言。在您的正则表达式中,(?<=mydomain.net)?意思是“当前位置在前面mydomain.net或不在前面;我不在乎。”

无论如何,乍得已经想出了一个有效的正则表达式;我只是想提供一些关于为什么你没有的见解。当然,还要现场测试我的反模式。;)

于 2010-02-17T03:03:43.817 回答
2

这似乎适用于我编写的测试

/Resource:\s(?:.*myserver.net)?(?<PartIWant>.*)\s(?:State)/

如果您的正则表达式引擎支持命名捕获组,它将位于命名捕获组“PartIWant”中。

编辑:我已经用这两个字符串测试了这个正则表达式

[HQ] !!! - Alert: My Demo Website Alert Resource: demo.myserver.net Apache Web Server State: fixed
[HQ] !!! - Alert: My Demo Website Alert Resource: Apache Web Server State: fixed
于 2010-02-16T21:05:23.083 回答
1

有时,事情可以做得很简单。用您最喜欢的语言,在“myserver.net”上进行拆分,然后在第一个元素的“State:”上进行拆分。例如在 Python 中

>>> s="""[HQ] !!! - Alert: My Demo Website Alert Resource: demo.myserver.net Apache Web Server State: fixed"""
>>> s.split("myserver.net")[-1].split("State:")[0]
' Apache Web Server '
于 2010-02-17T03:10:30.183 回答