例如,此正则表达式
(.*)<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>/s
re.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
/ stringi
regex功能,也可以使用(?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 \
或s
or 匹配的方括号表达式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)
则$3
is (<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