什么是匹配和捕获以未定义数量的新行为前提的多行字符串的正则表达式?[PCRE系列]

What is any regular expression that matches and capture a multiline string predeced by an undefined number of new lines? [PCRE]

提问人:Paiku Han 提问时间:11/5/2023 最后编辑:InSyncPaiku Han 更新时间:11/5/2023 访问量:64

问:

我有这个多行字符串:

Lorem ipsum dolor sit amet.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
dictum, lorem et fringilla congue, velit libero sagittis eros, id
lobortis nisi risus ac mauris.

我想使用PHP兼容的正则表达式来“命名捕获”第二个“段落”(新行之后的3行文本)。

我在 regex101 上尝试了以下正则表达式,它工作正常:

/\n(\n)+(?<namedGroup>([\w\d]+.*(\n)?)+)/m

但是当我使用以下代码在PHP中尝试时,什么都没有捕获到:

<?php
$text = file_get_contents("paragraphs.txt");

$regular_expression = '/\n(\n)+(?<namedGroup>([\w\d]+.*(\n)?)+)/m';

preg_match($regular_expression, $text, $result);
print_r($result);
?>
php 正则 正则表达式组

评论

1赞 The fourth bird 11/5/2023
如果我使用问题中的文本运行您的代码,我确实会看到一个结果。3v4l.org/5MTA1你不需要标志,因为没有锚点,并且与/m[\w\d]+\w+
0赞 Paiku Han 11/5/2023
@Thefourthbird我在Apache服务器上测试了您的确切代码,但它不起作用。我正在运行 PHP 7.4.33。难道是它不起作用的原因吗?
1赞 Olivier 11/5/2023
删除字符,它将起作用:.\r$text = str_replace("\r", "", $text);
1赞 The fourth bird 11/5/2023
尝试像这样运行它,只匹配 3v4l.org/JSU0J$regular_expression = '/\R{2}\K\w.*(?:\R\w.*)*/';
2赞 IMSoP 11/5/2023
您可以自己确认这与该链接上的PHP版本无关;这里它在 7.4 中运行良好: 3v4l.org/5MTA1#v7.4.33 因此,您保存文件的方式很可能意味着它并不完全相同 - Olivier 的评论暗示了您有 Windows 行结尾的猜测,这些行结尾与模式中的 \n 不匹配。

答:

1赞 The fourth bird 11/5/2023 #1

目前,您正在使用这样的模式,为此可以进行一些改进:

$regular_expression = '/\n(\n)+(?<namedGroup>([\w\d]+.*(\n)?)+)/m';

您只匹配换行符,显然您的文件中有换行符。要匹配这些,您可以使用这些换行符来匹配任何 Unicode 换行符序列。\n\r\n\R

如果您只想匹配单个值,则实际上可以在使用丢弃到目前为止匹配的内容时完全省略该组。(?<namedGroup>\K

请注意:

  • [\w\d]与 as 也匹配数字相同\w
  • 您的模式总共有 4 个捕获组,其中只有命名的捕获组就足够了
  • 您不需要多行标志,因为模式中没有锚点/m
  • 该模式仅匹配以单词字符开头的行\w
  • 与感兴趣的匹配项无关,但像这样重复捕获组只会捕获上次迭代的值(\n)+

可用于单次匹配的更新模式:

\R{2,}\K\w.*(?:\R\w.*)*
  • \R{2,}匹配 2 个或多个 Unicode 换行符序列
  • \K忘记到目前为止匹配的内容
  • \w.*匹配单词字符和行的其余部分
  • (?:\R\w.*)*(可选)重复 Unicode 换行符序列、单词字符和行的其余部分

或者仅匹配以非空格字符开头的行\S

\R{2,}\K\S.*(?:\R\S.*)*

正则表达式演示 |Php 演示

评论

1赞 Paiku Han 11/5/2023
好的,现在我明白了什么是用的。我在修补我的正则表达式时弄清楚了什么是用的。\K\R