【问题标题】:Regex problem: Can't match a variable length pattern正则表达式问题:无法匹配可变长度模式
【发布时间】:2023-03-27 09:45:01
【问题描述】:

我对正则表达式有疑问,使用 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() 将它们变成一个很长的单行字符串,没有换行符......

【问题讨论】:

  • 我很困惑 - 你能显示你想要的输出/匹配吗?
  • 我想提取'Congestions:'后面的词,即每条高速公路的交通状况。

标签: php regex preg-match-all


【解决方案1】:

您可以尝试最小匹配:

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

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

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

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

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

【讨论】:

  • 非常感谢! :) 这行得通。我知道 .* 会匹配多个或任何东西,但是有什么作用呢?什么时候加入到混合物中?
  • 量词 (*, +, ?, {n,m}) 后的问号 (?) 强制进行最小匹配,例如,如果正则表达式 (test)+ 匹配一次字符串testtesttesttest,正则表达式(测试)+?将匹配它四次。
【解决方案2】:
Congestion\s*:\s*Traffic is\s*(?P<c1>[^\n]*)\s*from\s*(?P<c2>[^\n]*)\s*to\s*(?P<c3>[^\n]*)$

【讨论】:

  • 不幸的是,这不起作用。 (?P.*) 已经匹配到第 3 个实例结束,第一次匹配。
  • @blacklotus Dot 不应匹配换行符,除非用 DOTALL 标志指定 - 无论如何,将 . 替换为 [^\n]
  • 它们实际上都在一行中,这就是原因。我必须在这里很好地格式化它们,否则你将无法看到模式。
【解决方案3】:

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

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

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

【讨论】:

  • 它们实际上不是多行的。它们实际上是随机中断的巨大文本块,我使用 json_encode() 形成单行字符串。必须在这里很好地格式化它们,否则我的问题会更加混乱。
  • @blacklotus:可惜。不过,只是为了检查一下:你从哪里得到的文本。 JSON 编码不应该与字符串的格式混淆(一旦正确解码)。
  • 这实际上是一封格式很差的 HTML 电子邮件。因此,在剥离 html 代码和一些随机的“=”和换行符之后,我使用 json_encode() 再次将它们形成一个巨大的字符串,这样随机换行符就不会影响匹配。实际上,我还必须匹配高速公路的名称和日期时间,但它们的模式是恒定的,因此匹配它们的模式要容易得多。真的有很多困难。
猜你喜欢
  • 2011-11-16
  • 1970-01-01
  • 2017-12-28
  • 1970-01-01
  • 1970-01-01
  • 2016-04-02
  • 2011-07-17
相关资源
最近更新 更多