如何避免正则表达式中的不同捕获组编号?

时间:2015-02-20 09:45:25

标签: regex if-statement regex-group

我正在尝试捕获日志中的IP地址,如果地址为0.0.0.0,则还原主机名。

以下是日志的一些示例:

Foo bar ip=0.0.0.0 baz host=YOLO-PC foobar bazinga

在这种情况下,我想要“YOLO-PC”,因为IP是0.0.0.0

Foo bar ip=12.23.34.45 baz host=FOOBAR-PC foobar bazinga

在这种情况下,我想要12.23.34.45

这是我试过的:

ip=(?:0\.0\.0\.0|(\d+\.\d+\.\d+\.\d+)).*?host=(?(1).|(\S+))

它有效,但是当IP为0.0.0.0时,它会创建第二个组,其后面的程序无法获取组#2,只能获取组#1。

我该怎么做?把它全部放在一个组中?有更好的解决方案吗?

3 个答案:

答案 0 :(得分:3)

从您的问题中不清楚您正在处理哪种环境/语言/正则表达式。但PCRE正则表达式实际上允许您使用(?|some(capture)|another(capture))语法执行此操作:

ip=(?|0\.0\.0\.0.*?host=(\S+)|(\d+\.\d+\.\d+\.\d+))

Regular expression visualization

您可以在debuggex visualisation中看到两个组的编号均为 1 。在regex101上,您可以看到右侧的捕获。

或者(如果你不使用PCRE),我想你可以这样做。它不那么严格,但适用于大多数引擎。您当前的正则表达式对IP格式并不特别严格(允许高于255的数字等),所以这对您来说可能不是问题。

ip=(?:0\.0\.0\.0.*?host=)?(\S+)

Regular expression visualization

Debuggex Demo

答案 1 :(得分:1)

结果中的组数等于正则表达式中( )组的数量。你引用它们的顺序是开头的parens出现在正则表达式中的顺序。有些组可能不匹配并且为空。

因此,在您的情况下,您将始终拥有两个小组。组1是非零ip,组2是主机名。如果IP为0.0.0.0,则组1将为空。如果没有,则第2组将为空。

您是否只能检查代码中哪个组为空并使用另一个组?

答案 2 :(得分:0)

使用从左到右尝试的替换:

(?<=ip)(?!0.0.0.0)\S+|(?<=host=)\S+

请参阅demo

由于使用环顾四周,这仅匹配您的目标输入。如果它全部为零,那么前面的负面看法决定不使用ip。

只选择第一个匹配。