例如,这个正则表达式
(.*)<FooBar>
将匹配:
abcde<FooBar>
但是如何让它跨多行匹配?
abcde
fghij<FooBar>
试试这个:
((.|\n)*)<FooBar>
它基本上说“任何字符或换行符”重复零次或多次。
这取决于语言,但应该有一个可以添加到正则表达式模式的修饰符。在 PHP 中是:
/(.*)<FooBar>/s
最后的s使点匹配所有字符,包括换行符。
问题是,.
模式可以匹配任何字符吗?答案因发动机而异。主要区别在于该模式是由 POSIX 还是非 POSIX 正则表达式库使用。
关于lua-patterns的特别说明:它们不被视为正则表达式,但.
匹配那里的任何字符,与基于 POSIX 的引擎相同。
关于matlab和octave的另一个说明:.
默认情况下匹配任何字符(演示):(str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');
包含tokens
一个abcde\n fghij
项目)。
此外,在所有boost的正则表达式语法中,点默认匹配换行符。regex_constants::no_mod_m
Boost 的 ECMAScript 语法允许您使用( source )将其关闭。
至于oracle(它基于 POSIX),请使用选项n
( demo ):select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual
基于 POSIX 的引擎:
A.
已经匹配换行符,因此不需要使用任何修饰符,请参阅bash ( demo )。
tcl ( demo ), postgresql ( demo ) , r (TRE, base R default engine with no perl=TRUE
, 对于 base R with perl=TRUE
or stringr / stringi模式,使用(?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
)。请注意, using-000pe
将 slurp 文件并激活“段落模式”,其中 Perl 使用连续的换行符 ( \n\n
) 作为记录分隔符。grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file
. 这里,z
启用文件 slurping,(?s)
启用模式的 DOTALL 模式.
,(?i)
启用不区分大小写模式,\K
省略到目前为止匹配的文本,*?
是一个惰性量词,(?=<Foobar>)
匹配之前的位置<Foobar>
。pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file
(M
在此处启用文件 slurping)。Notepcregrep
对于 macOSgrep
用户来说是一个很好的解决方案。见演示。
非基于 POSIX 的引擎:
php -使用s
修饰符PCRE_DOTALL 修饰符:(演示preg_match('~(.*)<Foobar>~s', $s, $m)
)
c# - 使用RegexOptions.Singleline
标志(演示):
- var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
-var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
powershell - 使用(?s)
内联选项:$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
python - 使用re.DOTALL
(or re.S
) 标志或(?s)
内联修饰符 ( demo ): m = re.search(r"(.*)<FooBar>", s, flags=re.S)
(然后if m:
, print(m.group(1))
)
java - 使用Pattern.DOTALL
修饰符(或内联(?s)
标志)(演示):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
scala - 使用(?s)
修饰符(演示):"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
javascript - 使用[^]
或解决方法[\d\D]
// [\w\W]
(演示)[\s\S]
:s.match(/([\s\S]*)<FooBar>/)[1]
c++ ( std::regex
) 使用[\s\S]
或 JavaScript 变通办法 ( demo ):regex rex(R"(([\s\S]*)<FooBar>)");
vba vbscript - 使用与 JavaScript 相同的方法,([\s\S]*)<Foobar>
. (注意:对象的MultiLine
属性RegExp
有时被错误地认为是允许.
跨换行符匹配的选项,而实际上,它只会更改^
and行为以匹配行$
的开始/结束而不是字符串,这与 JavaScript 中的相同正则表达式)行为。)
ruby - 使用/m
MULTILINE修饰符(演示):s[/(.*)<Foobar>/m, 1]
r tre base-r - Base R PCRE 正则表达式 -使用(?s)
:(演示)regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]
r icu stringr stringi -由 ICU 正则表达式引擎驱动的输入stringr
/正则表达式函数。stringi
也可以使用(?s)
:(演示stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]
)
go - 在开始时使用 inline 修饰符(?s)
(demo):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
swift - 使用dotMatchesLineSeparators
或(更容易)将(?s)
内联修饰符传递给模式:let rx = "(?s)(.*)<Foobar>"
objective-c - 与 Swift 相同。(?s)
工作最简单,但这里是如何使用该选项:NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:®exError];
re2,google-apps-script - 使用(?s)
修饰符(演示):("(?s)(.*)<Foobar>"
在 Google 电子表格中,=REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")
)
注意事项(?s)
:
在大多数非 POSIX 引擎中,(?s)
内联修饰符(或嵌入标志选项)可用于强制.
匹配换行符。
如果放置在模式的开头,则(?s)
更改模式中所有.
的行为。如果s(?s)
放在开头之后的某个位置,则只有.
位于其右侧的 s 会受到影响,除非这是传递给 Python 的re
. 在 Pythonre
中,无论(?s)
位置如何,整个模式.
都会受到影响。使用(?s)
停止效果(?-s)
。修改后的组可用于仅影响正则表达式模式的指定范围(例如,Delim1(?s:.*?)\nDelim2.*
将在换行符之间进行第一个.*?
匹配,而第二个.*
将仅匹配该行的其余部分)。
POSIX 注释:
在非 POSIX 正则表达式引擎中,要匹配任何字符,可以使用 // 构造[\s\S]
。[\d\D]
[\w\W]
在 POSIX 中,[\s\S]
不匹配任何字符(如在 JavaScript 或任何非 POSIX 引擎中),因为括号表达式内不支持正则表达式转义序列。[\s\S]
被解析为匹配单个字符的括号表达式,\
或s
或S
。
如果您使用的是 Eclipse 搜索,您可以启用“DOTALL”选项来制作 '.' 匹配任何字符,包括行分隔符:只需在搜索字符串的开头添加“(?s)”。例子:
(?s).*<FooBar>
在许多正则表达式方言中,/[\S\s]*<Foobar>/
会做你想做的事。来源
([\s\S]*)<FooBar>
点匹配除换行符 (\r\n) 之外的所有内容。所以使用 \s\S,它将匹配所有字符。
我们也可以使用
(.*?\n)*?
匹配所有内容,包括换行符而不贪心。
这将使新行可选
(.*?|\n)*?
"."
通常不匹配换行符。大多数正则表达式引擎允许您添加S
- 标志(也称为DOTALL
and SINGLELINE
)以"."
匹配换行符。如果失败,您可以执行类似[\S\s]
.
对于 Eclipse,以下表达式有效:
富
贾达哈达酒吧"
正则表达式:
Foo[\S\s]{1,10}.*Bar*
采用:
/(.*)<FooBar>/s
导致点 ( . s
) 匹配回车。
请注意,这(.|\n)*
可能比(例如)[\s\S]*
(如果您的语言的正则表达式支持此类转义)和查找如何指定使 . 也匹配换行符。或者您可以使用 POSIXy 替代方案,例如[[:space:][:^space:]]*
.
使用 RegexOptions.Singleline。它改变了.
包含换行符的含义。
Regex.Replace(content, searchText, replaceText, RegexOptions.Singleline);
在基于 Java 的正则表达式中,您可以使用[\s\S]
.
通常,.
不匹配换行符,因此请尝试((.|\n)*)<foobar>
.
在语言中使用的上下文中,正则表达式作用于字符串,而不是行。所以你应该能够正常使用正则表达式,假设输入字符串有多行。
在这种情况下,给定的正则表达式将匹配整个字符串,因为存在“<FooBar>”。根据正则表达式实现的具体情况,$1 值(从“(.*)”获得)将是“fghij”或“abcde\nfghij”。正如其他人所说,某些实现允许您控制是否“。” 将匹配换行符,给你选择。
基于行的正则表达式通常用于 egrep 之类的命令行。
我遇到了同样的问题,并以可能不是最好的方式解决了它,但它确实有效。在进行真正的比赛之前,我替换了所有换行符:
mystring = Regex.Replace(mystring, "\r\n", "")
我正在处理 HTML,所以在这种情况下,换行符对我来说并不重要。
我尝试了上面的所有建议,但没有运气。我正在使用 .NET 3.5 仅供参考。
在 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>
假设您也允许空白换行符。因为您允许任何字符,包括之前的任何内容<FooBar>
。
在记事本++中,您可以使用它
<table (.|\r\n)*</table>
它将匹配整个表从
行和列您可以使用以下方法使其变得贪婪,这样它将匹配第一个、第二个等表,而不是一次全部匹配
<table (.|\r\n)*?</table>
我想在 Java中匹配一个特定的if块:
...
...
if(isTrue){
doAction();
}
...
...
}
如果我使用正则表达式
if \(isTrue(.|\n)*}
它包括方法块的右大括号,所以我使用了
if \(!isTrue([^}.]|\n)*}
从通配符匹配中排除右大括号。
通常,我们必须使用分布在子字符串前面的行中的几个关键字来修改子字符串。考虑一个 XML 元素:
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>81</PercentComplete>
</TASK>
假设我们想将 81 修改为其他值,比如 40。首先确定.UID.21..UID.
,然后跳过包括\n
until在内的所有字符.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
就是 (<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