正则表达式捕获多行

时间:2011-07-11 20:37:10

标签: regex

我有一些这样的文字:

注意:这是示例文本,因此内容不重要

CAT SAT ON A DOG
REASON:  No reason
CONCERN:  He was cold
BECAUSE:  Cold weather

CAT SAT ON A MOUSE
REASON:  He eats mice
CONCERN:  He was hungry
BECAUSE:  Can opener didn't work

CAT SAT ON A HORSE
REASON:  He wants to ride
CONCERN:  He might fall off
BECAUSE:  Saddle is too big

我正在尝试编写一个正则表达式,只能捕获“鼠标上的CAT SAT”部分,但是在捕获全文时遇到问题。

我试过了:

(\bCAT\sSAT\sON\sA\sMOUSE)(.*)\n{2}

这个想法是匹配字符串的开头部分,然后捕获所有内容直到两个换行符。

{2}是捕获两个换行符。

我尝试过更多变种,但我设法做的只是捕获第一行。

非常感谢任何形式的帮助。

4 个答案:

答案 0 :(得分:2)

你要求两个换行符。 您需要要求换行,然后两次。

试试这个:

(\bCAT\sSAT\sON\sA\sMOUSE)(\n.*){2}

答案 1 :(得分:1)

我认为您的主要问题是您的文字使用\r\n来分隔行,而您只是在寻找\n。试试这个:

/^(CAT +SAT +ON +A +MOUSE)(?:(?:\r\n|[\r\n])[^\r\n]+)*/m

(?:\r\n|[\r\n])匹配三个最常见的行分隔符(我称之为换行符)中的任何一个:\r\n\r或{{1} }。它一次只匹配一个换行符,无论它是哪种换行符。然后\n接管,因此每行只能有一个行分隔符。由于段落由两个换行符分隔,因此匹配结束。

我冒昧地在多线模式([^\r\n]+)中使用起始锚点(^)锚定第一行。这并非绝对必要,但有助于正则表达式更快地找到匹配,更重要的是,当不可能匹配时更快地失败。

(你还没有说过你正在使用哪种正则表达式,所以我猜测并使用了JavaScript语法。)

答案 2 :(得分:0)

您使用的是哪种语言?那会有所帮助。在Perl中,您可以添加m说明符以将多行字符串视为单个文本:

#! /usr/bin/perl

my $string =<<STRING;
CAT SAT ON A MOUSE
REASON:  He eats mice
CONCERN:  He was hungry
BECAUSE:  Can opener didn't work

This is a test, and not part of the string to match.
STRING

if ($string =~ /(^(CAT[^\n]+).*\n\n/s) {
    say "Match: $1";
}
else {
    say "Didn't match";
}

在Perl中,在末尾添加s会将输入字符串视为一行。

答案 3 :(得分:0)

这可能有效:

(\bCAT[^\S\n]SAT[^\S\n]ON[^\S\n]A[^\S\n]MOUSE\b[\s\S]*?)\n{2}

(\bCAT[^\S\n]+SAT[^\S\n]+ON[^\S\n]+A[^\S\n]+MOUSE\b[\s\S]*?)\n{2}

编辑 - 必须在第一个锚之后减慢正则表达式,否则下一个锚点 可能会被放弃以支持速度。这可以通过非贪婪的量词来完成 或者前瞻性断言(允许以支票为代价的攻击性行为) 这基本上会使其速度无效。)

Edit2 - 有时可能需要匹配可能包含非换行空格的段落之间的“明显”差距。

例如\n\n与这样的明显差距不匹配:
 当它应该开始时,开始... \ nnd of段\ n \ n'。

在这种情况下,将\n{2}替换为\n[^\S\n]*\n将允许它匹配 此外,由于使用了非贪婪量词(在这种情况下)\b[\s\S]*?
当文件结尾或接近文件末尾时,可以考虑并匹配段落结尾。把这些全部放在一起:

/(\bCAT\s+SAT\s+ON\s+A\s+MOUSE\b[\s\S]*?)($|\n[^\S\n]*\n)/

现在看起来很复杂,但完成了这项工作。