Preg_match 返回 "extra" 新行的空匹配

Preg_match returning "extra" empty matches for new lines

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

仅具有可选模式的正则表达式始终可以在不匹配的字符序列之前匹配空字符串。

您可以使用

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
//   )

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

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

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

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

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

看到一个regex demo