我有一些这样的文字:
注意:这是示例文本,因此内容不重要
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}是捕获两个换行符。
我尝试过更多变种,但我设法做的只是捕获第一行。
非常感谢任何形式的帮助。
答案 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)/
现在看起来很复杂,但完成了这项工作。