正则表达式问题:无法匹配可变长度模式

时间:2010-10-18 10:08:57

标签: php regex preg-match-all

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

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

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

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

现在,由于拥塞背后的词语可能有不同的长度,我无法真实地预测它们之间有多少单词和空格来提出更严格的\ 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()分解为一个非常长的单行字符串,没有换行...

3 个答案:

答案 0 :(得分:4)

通常,正则表达式匹配是基于行的。正则表达式假设您的字符串是单行。您可以使用m” (PCRE_MULTILINE) flag更改该行为。然后你可以告诉PHP只匹配行的末尾:

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

有两点需要注意:首先,修改模式以包括line-begin(^)和line-end($)标记。其次,模式现在带有m修饰符。

答案 1 :(得分:2)

Congestion\s*:\s*Traffic is\s*(?P<c1>[^\n]*)\s*from\s*(?P<c2>[^\n]*)\s*to\s*(?P<c3>[^\n]*)$

答案 2 :(得分:2)

您可以尝试最小匹配:

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

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

因此,如果“高速公路”始终启动交通状况记录,则可以修复此问题:

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

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