如何匹配正则表达式直到出现 2 个换行符

How to match regex untill 2 linebreaks

我正在尝试从 Lexis Nexis 获得的一些新闻文章中删除元数据。我目前在剥离多行元数据时遇到了一些问题,即:我的模式只匹配第一行。

我怀疑这可以通过寻找多个换行符的负前瞻来解决,但到目前为止我还无法解决。

$article = "SECTION: Media; Blz. 33

LENGTH: 355 woorden

HIGHLIGHT: Verkiezingen Robert Jensen keert vanaf vandaag terug op de
Nederlandse televisie. In 'Jensen kiest voor Amerika' onderzoekt hij de
aantrekkingskracht van Donald Trump. Is hij definitief terug of lonkt misschien
een oude liefde?

Waarom ben je Jensen kiest voor Amerika gaan maken?

,,Ik vind Amerika al mijn hele leven een fascinerend land, ben er vaak en volg
de verkiezingen als fenomeen. Toen Trump maar bleef winnen, begon het idee voor
een tv-programma te leven. Ik wilde alles van die Trump-aanhangers weten want
daar hoor je weinig over.''";

preg_match_all( "/[A-Z\h-]+: *[^\r]+/", $article, $matches);

var_dump( $matches[0] );
die();

结果:

array(3) { [0]=> string(23) "SECTION: Media; Blz. 33" [1]=> string(19) "LENGTH: 355 woorden" [2]=> string(70) "HIGHLIGHT: Verkiezingen Robert Jensen keert vanaf vandaag terug op de" } 

因为你只能匹配highlight数据的第一行。

我还在 regex101 上发布了一篇完整的文章(包含多行元数据的多个示例)。

编辑:

经过两次回答后,我意识到我的问题可能没有完全清楚 -- 对此感到抱歉。

我正在尝试 strip/remove 来自 $article 的元数据,以便仅保留文章的正文。在我的示例中,我使用 preg_match_all()。一旦我可以正确匹配元标记,我将使用 preg_replace() 将其替换为空字符串。我考虑过使用 preg_split(),但我不得不猜测数组项中的哪一个是实际正文——元标记可能比实际正文更长,尽管这不太可能发生。

那么什么是元标签?元标记始终以 [A-Z\h-]+: 开头并以空行结束,即两个换行符。

如果您采用上述示例并将标签放在一个数组中,将文章正文放在一个单独的变量中,它看起来像这样:

<?php
$meta_tags = [
"SECTION"   => "Media; Blz. 33",
"LENGTH"    => "355 woorden",
"HIGHLIGHT" => "Verkiezingen Robert Jensen keert vanaf vandaag terug op de
Nederlandse televisie. In 'Jensen kiest voor Amerika' onderzoekt hij de
aantrekkingskracht van Donald Trump. Is hij definitief terug of lonkt misschien
een oude liefde?"
];

$article_body = "Waarom ben je Jensen kiest voor Amerika gaan maken?

,,Ik vind Amerika al mijn hele leven een fascinerend land, ben er vaak en volg
de verkiezingen als fenomeen. Toen Trump maar bleef winnen, begon het idee voor
een tv-programma te leven. Ik wilde alles van die Trump-aanhangers weten want
daar hoor je weinig over.''";

补充说明:正文文章后可能还有一些元标记,但元标记上的 preg_replace() 也应注意这一点。

由于您没有复杂的匹配要做,您也可以使用简单的 preg_split() 将元数据键作为分隔符,而不用担心前瞻等问题:

$matches = preg_split( '/\v*([A-Z\h-]+):\h?/', $article, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

给你:

array(6) {
  [0]=> string(7) "SECTION"
  [1]=> string(14) "Media; Blz. 33"
  [2]=> string(6) "LENGTH"
  [3]=> string(11) "355 woorden"
  [4]=> string(9) "HIGHLIGHT"
  [5]=> string(556) "Verkiezingen Robert Jensen keert vanaf vandaag terug op de
Nederlandse televisie. In 'Jensen kiest voor Amerika' onderzoekt hij de
aantrekkingskracht van Donald Trump. Is hij definitief terug of lonkt misschien
een oude liefde?

Waarom ben je Jensen kiest voor Amerika gaan maken?
/...snip/"
}

...我相信您可以很容易地继续处理,偶数是键,赔率是值。 ^_^


但是如果你确实想使用前瞻,这里有一个例子:

preg_match_all('/[A-Z\h-]+:.*?(?=\s*(?:[A-Z\h-]+:|\Z))/s', $article, $matches);

这匹配任何以您的元键开头,后跟另一个元键或数据结尾的任何内容。最好不要担心在这里匹配换行符,而是匹配重要的内容。前瞻可以进一步简化为 (?=[A-Z\h-]+:|\Z),但 \s* 会修剪值中尾随的 space。 (这就是为什么随后的实际前瞻组被指定为 ?: 非捕获,我们现在不想让输出混乱。)结果:

array(3) {
  [0]=> string(23) "SECTION: Media; Blz. 33"
  [1]=> string(19) "LENGTH: 355 woorden"
  [2]=> string(567) "HIGHLIGHT: Verkiezingen Robert Jensen keert vanaf vandaag terug op de
Nederlandse televisie. In 'Jensen kiest voor Amerika' onderzoekt hij de
aantrekkingskracht van Donald Trump. Is hij definitief terug of lonkt misschien
een oude liefde?

Waarom ben je Jensen kiest voor Amerika gaan maken?
/...snip/"
}

但是如果你想让它好看,不如这样做:

preg_match_all('/([A-Z\h-]+):\h*(.*?)(?=\s*(?:[A-Z\h-]+:|\Z))/s', $article, $matches);
$parsed = array_combine($matches[1], $matches[2]);

也就是说,我们为键和值添加捕获组,然后将它们组合成一个关联数组。 (在尝试合并之前请检查您是否有匹配项。)结果:

array(3) {
  ["SECTION"]=> string(14) "Media; Blz. 33"
  ["LENGTH"]=> string(11) "355 woorden"
  ["HIGHLIGHT"]=> string(556) "Verkiezingen Robert Jensen keert vanaf vandaag terug op de
Nederlandse televisie. In 'Jensen kiest voor Amerika' onderzoekt hij de
aantrekkingskracht van Donald Trump. Is hij definitief terug of lonkt misschien
een oude liefde?

Waarom ben je Jensen kiest voor Amerika gaan maken?
/...snip/"
}

编辑 如果你真正想要的只是正文(既然正文开始的位置很清楚:在一段高亮元之后),你没有用对于元数据,然后只需使用 preg_replace 匹配所有以元键开头的部分来清理文章,并匹配所有内容,直到第一个双(或更多)换行符。 (使用 \v 匹配任何垂直 space。)

$article = preg_replace('/([A-Z\h-]+):\h*(.*?)[\v]{2,}/s', '', $article);

这可能是您要找的:

^(?P<key>[A-Z]+):
(?P<value>(?:(?!^[A-Z]+:).)+)

a demo on regex101.com