【问题标题】:Preg_match returning "extra" empty matches for new linesPreg_match 为新行返回“额外”的空匹配
【发布时间】:2021-05-17 19:48:19
【问题描述】:

以下表达式返回我需要的内容,但为每个表达式以及任何空行提供了一个额外的空匹配。这会导致 5 个有效文本行返回 10 个匹配项。我预计这是我指定最后一个捕获组的方式,或者不需要 Capture Group #2。

如何“忽略”换行符(或触发额外匹配的任何内容)

/(\d+[a-z]?\.)?[ ]?(.*)/g

11a. A numbered agenda item
Unnumbered agenda item
12. Another numbered agenda item
Another UNnumbered agenda item
13. A numbered agenda item

我需要提取议程项目文本和前面的数字(如果存在)。

https://regex101.com/r/vB0H5s/1的演示

【问题讨论】:

  • 所有量词都是可选的,也匹配一个空字符串。您可以更改末尾的 (.+) 以匹配至少 1 个字符。

标签: php regex preg-match


【解决方案1】:

在您的模式中,您使用的量词 ?* 都是可选的,也可以匹配空字符串。

您得到 10 个匹配而不是 5 个的原因是该模式是未锚定的。由于所有部分都是可选的,最后一个.* 可以“匹配”字符串中的最后一个位置。

您可以使用(.+) 在第二个捕获组中捕获 1 个或多个字符。

如果匹配应该在字符串的开头,您可以使用锚点^

^(\d+[a-z]?\.)?[ ]?(.+)

查看regex demo

【讨论】:

    【解决方案2】:

    带有可选模式的正则表达式只能在不匹配的字符序列之前匹配空字符串。

    你可以使用

    preg_match_all('/^(\d+[a-z]?\.)\s*(.*(?:\R(?!\d+[a-z]?\.).*)*)/m', $text, $matches)
    

    请参阅regex demo

    详情

    • ^ - 行首
    • (\d+[a-z]?\.) - 第 1 组:一个或多个数字、一个可选字母和一个 .
    • \s* - 零个或多个空格
    • (.*(?:\R(?!\d+[a-z]?\.).*)*) - 第 2 组:行的其余部分,换行序列后不跟一个或多个数字、一个可选字母和一个 .,然后是行的其余部分,零次或多次。

    PHP demo

    $text = "11a. A numbered agenda item\nUnnumbered agenda item\n12. Another numbered agenda item\nAnother UNnumbered agenda item\n13. A numbered agenda item";
    if (preg_match_all('/^(\d+[a-z]?\.)\s*(.*(?:\R(?!\d+[a-z]?\.).*)*)/m', $text, $matches)) {
         print_r(array_combine($matches[1], $matches[2]));
    }
    // => Array
    //   (
    //     [11a.] => A numbered agenda item
    //     Unnumbered agenda item
    //     [12.] => Another numbered agenda item
    //     Another UNnumbered agenda item
    //     [13.] => A numbered agenda item
    //   )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-01
      相关资源
      最近更新 更多