例如,此正则表达式
(.*)<FooBar>
将匹配:
abcde<FooBar>
但是我如何才能使其跨多行匹配?
abcde
fghij<FooBar>
例如,此正则表达式
(.*)<FooBar>
将匹配:
abcde<FooBar>
但是我如何才能使其跨多行匹配?
abcde
fghij<FooBar>
Answers:
它取决于语言,但是应该有一个可以添加到正则表达式模式的修饰符。在PHP中是:
/(.*)<FooBar>/s
末尾的s使点匹配所有字符,包括换行符。
s修饰符。相反,[^]*要达到相同的效果。
m修饰符
尝试这个:
((.|\n)*)<FooBar>
它基本上说“任何字符或换行符”重复零次或多次。
((.|\n|\r)*)<FooBar>
[\s\S]*或(?s).*。
问题是,.模式可以匹配任何字符吗?答案因引擎而异。主要区别在于该模式是由POSIX还是非POSIX正则表达式库使用的。
关于特别说明 lua模式:它们不被认为是正则表达式,但.与基于POSIX的引擎相同,可以匹配其中的任何char。
另一个注意 Matlab的 和 八度:在.默认情况下,任何字符(匹配演示): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');(tokens含abcde\n fghij项目)。
而且,在所有 促进的regex语法默认情况下点匹配换行符。Boost的ECMAScript语法使您可以使用regex_constants::no_mod_m(source)将其关闭。
至于 甲骨文(基于POSIX),使用n选项(demo):select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual
基于POSIX的引擎:
的 tcl(演示),PostgreSQL(演示),[R(TRE,不带base R的默认引擎perl=TRUE,对于具有perl=TRUE或用于stringr / stringi模式的base R ,请使用(?s)inline修饰符)(demo)也.以相同的方式处理。
但是,大多数基于POSIX的工具都是逐行处理输入的。因此,.由于行号不在范围内,因此与行号不匹配。以下是一些如何覆盖此示例:
sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'(H;1h;$!d;x;将文件拖入内存)。如果必须包括整行,则可以考虑sed '/start_pattern/,/end_pattern/d' file(从开始删除将以包括匹配的行结束)或sed '/start_pattern/,/end_pattern/{{//!d;};}' file(不包括匹配的行)。perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"(-0将整个文件保存到内存中,-p应用给出的脚本后打印文件-e)。请注意,-000pe在Perl使用连续换行符(\n\n)作为记录分隔符的情况下,using 将对文件进行处理并激活“段落模式” 。grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file。在这里,z启用文件特征分析,(?s)为模式启用DOTALL模式.,(?i)启用不区分大小写的模式,\K省略到目前为止*?已匹配的文本,是一个懒惰的量词,(?=<Foobar>)之前匹配的位置<Foobar>。pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file(M在此处启用文件拖曳功能)。pcregrep对于Mac OS grep用户而言,Note 是一个很好的解决方案。参见演示。
非基于POSIX的引擎:
s修改PCRE_DOTALL修饰符:preg_match('~(.*)<Foobar>~s', $s, $m)(演示)RegexOptions.Singleline标志(演示var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;(?s)内联选项:$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]s修饰符(或(?s)开始时使用内联版本)(demo):/(.*)<FooBar>/sre.DOTALL(或re.S)标志或(?s)内联修饰符(demo):(m = re.search(r"(.*)<FooBar>", s, flags=re.S)然后if m:是print(m.group(1)))Pattern.DOTALL修饰符(或内联(?s)标志)(demo):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)(?s)模式内修饰符(demo):regex = /(?s)(.*)<FooBar>/(?s)修饰符(demo):"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }[^]或解决方法[\d\D]/ [\w\W]/ [\s\S](演示):s.match(/([\s\S]*)<FooBar>/)[1]std::regex)使用[\s\S]或JS解决方法(demo):regex rex(R"(([\s\S]*)<FooBar>)");vba 脚本-使用与JavaScript中相同的方法([\s\S]*)<Foobar>。(注:本MultiLine该财产
RegExp的对象有时错误地认为是允许选择.跨行匹配,而事实上,它只会改变^和$行为,以匹配开始/结束线,而不是字符串,相同JS正则表达式)的行为。)
红宝石-使用/m MULTILINE修饰符(demo):s[/(.*)<Foobar>/m, 1]
(?s):regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2](演示)stringr/ stringiregex功能,也可以使用(?s):stringr::str_match(x, "(?s)(.*)<FooBar>")[,2](demo)(?s)在开始时使用inline修饰符(demo):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)dotMatchesLineSeparators或(更轻松)将(?s)内联修饰符传递给模式:let rx = "(?s)(.*)<Foobar>"(?s)最简单,但是可以使用以下选项:NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionDotMatchesLineSeparators error:®exError];(?s)修饰符(demo):("(?s)(.*)<Foobar>"在Google Spreadsheets中,=REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))注意事项(?s):
在大多数非POSIX引擎中,(?s)可以使用内联修饰符(或嵌入式标志选项)来强制.匹配换行符。
如果放置在模式的开头,请(?s)更改模式中所有行为.。如果将(?s)放置在开始位置之后,则只会.影响位于其右侧的内容,除非这是传递给Python的模式re。在Python中re,无论(?s)位置在哪里,整个模式都会.受到影响。该(?s)效果被停止使用(?-s)。修改后的组只能用于影响正则表达式模式的指定范围(例如,Delim1(?s:.*?)\nDelim2.*使第一个.*?匹配跨换行,而第二个.*匹配仅匹配行的其余部分)。
POSIX注意事项:
在非POSIX正则表达式引擎,以匹配任何字符,[\s\S]/ [\d\D]/ [\w\W]构建体都可以使用。
在POSIX中,[\s\S]不匹配任何字符(如JavaScript或任何非POSIX引擎中的字符),因为括号表达式内不支持正则表达式转义序列。[\s\S]被解析为与单个char \或sor 匹配的方括号表达式S。
#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m的正则表达式标志设置一个基本标志定义,以反映这一点。并且Arrbitor 始终是内联修饰符。在哪里(?-sm)(?s).*重置。
.匹配那里的任何字符(包括换行符)。请参阅此在线Bash演示。
Go答案在内的荣誉和额外投票!
如果您使用的是Eclipse搜索,则可以启用“ DOTALL”选项将其设为“。”。匹配任何字符,包括行定界符:只需在搜索字符串的开头添加“(?s)”。例:
(?s).*<FooBar>
(?s)=>(?m)
"."通常与换行符不匹配。大多数正则表达式引擎都允许您添加S-flag(也称为DOTALL和SINGLELINE)以使其"."也匹配换行符。如果失败,则可以执行[\S\s]。
/(.*)<FooBar>/s
s使点(。)匹配回车符
s标志存在于PCRE中,PCRE是最完整的引擎(在Perl和PHP中可用)。PCRE有10个标志(以及许多其他功能),而JavaScript只有3个标志(gmi)。
在基于Java的正则表达式中,您可以使用 [\s\S]
s标记添加到Java中的模式中,而JavaScript没有该s标记。
使用模式修饰符sU将在PHP中获得所需的匹配。
preg_match('/(.*)/sU',$content,$match);
http://dreamluverz.com/developers-tools/regex-match-all-includes-new-line http://php.net/manual/en/reference.pcre.pattern.modifiers.php
我遇到了同样的问题,并可能不是以最佳方式解决了它,但它确实有效。在进行真正的比赛之前,我替换了所有换行符:
mystring= Regex.Replace(mystring, "\r\n", "")
我正在处理HTML,因此在这种情况下换行符对我而言并不重要。
我没有运气就尝试了上面的所有建议,我正在使用.Net 3.5 FYI
(\s|\S)似乎可以帮我这个忙!
(?s)做出.匹配任何字符。不要使用(\s|\S)那会降低性能。
在Javascript中,您可以使用[^] *搜索零到无限个字符,包括换行符。
$("#find_and_replace").click(function() {
var text = $("#textarea").val();
search_term = new RegExp("[^]*<Foobar>", "gi");;
replace_term = "Replacement term";
var new_text = text.replace(search_term, replace_term);
$("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij<Foobar></textarea>
通常。与换行符不匹配,请尝试((.|\n)*)<foobar>
\r。:((?:.|\r?\n)*)<foobar>
通常,我们必须使用一些关键字来修改子字符串,这些关键字分布在子字符串之前的行中。考虑一个xml元素:
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>81</PercentComplete>
</TASK>
假设我们想将81修改为其他值,例如40。首先确定.UID.21..UID.,然后跳过所有字符,包括\n直到.PercentCompleted.。正则表达式模式和替换规范为:
String hw = new String("<TASK>\n <UID>21</UID>\n <Name>Architectural design</Name>\n <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.
String iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>40</PercentComplete>
</TASK>
该子组(.|\n)可能是缺少的组$3。如果我们不进行捕获,(?:.|\n)则$3is (<PercentComplete>)。因此,模式replaceSpec也可以是:
pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")
并且替换可以像以前一样正常工作。
通常在Powershell中搜索三个连续的行,看起来就像:
$file = get-content file.txt -raw
$pattern = 'lineone\r\nlinetwo\r\nlinethree\r\n' # "windows" text
$pattern = 'lineone\nlinetwo\nlinethree\n' # "unix" text
$pattern = 'lineone\r?\nlinetwo\r?\nlinethree\r?\n' # both
$file -match $pattern
# output
True
奇怪的是,这将是提示符下的unix文本,但是文件中的Windows文本:
$pattern = 'lineone
linetwo
linethree
'
这是打印行尾的一种方法:
'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'
# output
lineone\nlinetwo\nlinethree\n