2

我有一个正则表达式的问题,使用 preg_match_all() 来匹配可变长度的东西。

我要匹配的是“拥塞”一词之后的交通状况我想出的是这个正则表达式模式:

Congestion\s*:\s*(?P<congestion>.*)

但是,它会将第一个实例一直提取到整个主题的末尾,因为 .* 会匹配所有内容。但这不是我想要的,我希望它作为 3 个实例单独匹配。

现在由于 Congestion 后面的单词可能是可变长度的,我无法真正预测之间有多少单词和空格来提出更严格的 \w*\s*\w* 匹配等。

关于我如何从这里开始的任何线索?

Highway : Highway 26
Datetime : 18-Oct-2010 05:18 PM
Congestion : Traffic is slow from Smith St to Alice Springs St

Highway : Princes Highway
Datetime : 18-Oct-2010 05:18 PM
Congestion : Traffic is slow at the Flinders St / Elizabeth St intersection

Highway : Eastern Freeway
Datetime : 18-Oct-2010 05:19 PM
Congestion : Traffic is slow from Prince St to Queen St

为清晰而编辑

这些格式非常精美的文本实际上是通过格式非常糟糕的 html 电子邮件收到的。它在这里和那里包含随机换行符,例如“拥堵:交通\n 从 Prince\nSt 到 Queen St 很慢”。

因此,在处理电子邮件时,我剥离了所有 html 代码和随机换行符,并将它们 json_encode() 转换为一个非常长的单行字符串,没有换行符......

4

3 回答 3

4

通常,正则表达式匹配是基于行的。正则表达式假定您的字符串是单行。您可以使用“<code>m”(PCRE_MULTILINE)标志来更改该行为。然后你可以告诉 PHP 只匹配到行尾:

preg_match('/^Congestion\s*:\s*(?P<congestion>.*)$/m', $subject, $matches);

有两点需要注意:首先,模式被修改为包括行开始 ( ^) 和行结束 ( $) 标记。其次,模式现在带有m修饰符。

于 2010-10-18T10:14:20.730 回答
2

您可以尝试最小匹配:

Congestion\s*:\s*(?P<congestion>.*?)

这将导致在命名组“拥塞”中返回零个字符,除非您可以在拥塞字符串之后立即匹配某些内容。

因此,如果“高速公路”总是启动交通状况记录,则可以解决此问题:

Congestion\s*:\s*(?P<congestion>.*?)Highway\s*:

如果这有效(我没有检查过),那么第一条记录匹配但最后一条记录不匹配!这可以通过在输入字符串的末尾附加文本“Highway :”来轻松解决。

于 2010-10-18T11:24:06.837 回答
2
Congestion\s*:\s*Traffic is\s*(?P<c1>[^\n]*)\s*from\s*(?P<c2>[^\n]*)\s*to\s*(?P<c3>[^\n]*)$
于 2010-10-18T10:13:45.720 回答