【发布时间】:2025-11-30 07:00:02
【问题描述】:
例如,这个正则表达式
(.*)<FooBar>
将匹配:
abcde<FooBar>
但是如何让它匹配多行呢?
abcde
fghij<FooBar>
【问题讨论】:
-
澄清一下;我最初使用 Eclipse 在多个文件中进行查找和替换。我通过下面的答案发现我的问题是工具而不是正则表达式模式。
例如,这个正则表达式
(.*)<FooBar>
将匹配:
abcde<FooBar>
但是如何让它匹配多行呢?
abcde
fghij<FooBar>
【问题讨论】:
试试这个:
((.|\n)*)<FooBar>
它基本上说“任何字符或换行符”重复零次或多次。
【讨论】:
((.|\n|\r)*)<FooBar>
[\s\S]* 或(?s).*。
这取决于语言,但应该有一个可以添加到正则表达式模式的修饰符。在 PHP 中是:
/(.*)<FooBar>/s
末尾的 s 使点匹配 所有 个字符,包括换行符。
【讨论】:
s 修饰符。相反,请执行 [^]* 以获得相同的效果。
m 修饰符
问题是,. 模式可以匹配 any 字符吗?答案因发动机而异。主要区别在于该模式是由 POSIX 还是非 POSIX 正则表达式库使用。
关于 lua-patterns 的特别说明:它们不被视为正则表达式,但 . 匹配那里的任何字符,与基于 POSIX 的引擎相同。
关于matlab 和octave 的另一个说明:. 默认匹配任何字符(demo):str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');(tokens 包含abcde\n fghij 项)。
此外,在所有boost 的正则表达式语法中,点默认匹配换行符。 Boost 的 ECMAScript 语法允许您使用 regex_constants::no_mod_m (source) 将其关闭。
至于oracle(基于POSIX),使用the n option(demo):select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual
基于 POSIX 的引擎:
仅. 已经匹配换行符,因此不需要使用任何修饰符,请参阅bash (demo)。
tcl (demo)、postgresql (demo)、r(TRE,基本 R 默认引擎,不带 perl=TRUE,用于带 perl=TRUE 的基本 R 或 stringr/stringi 模式,使用(?s) 内联修饰符)(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) 作为记录分隔符。grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file。这里,z 启用文件 slurping,(?s) 启用 . 模式的 DOTALL 模式,(?i) 启用不区分大小写模式,\K 省略到目前为止匹配的文本,*? 是一个惰性量词,@ 987654421@ 匹配<Foobar> 之前的位置。pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file(M 在此处启用文件 slurping)。注意pcregrep 是 macOS grep 用户的一个很好的解决方案。非 POSIX 引擎:
php - 使用 s 修饰符 PCRE_DOTALL modifier: preg_match('~(.*)<Foobar>~s', $s, $m) (demo)
c# - 使用 RegexOptions.Singleline 标志 (demo):
- 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(或re.S)标志或(?s)内联修饰符(demo):m = re.search(r"(.*)<FooBar>", s, flags=re.S)(然后是if m:,print(m.group(1)))
java - 使用 Pattern.DOTALL 修饰符(或内联 (?s) 标志)(demo):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
kotlin - 使用 RegexOption.DOT_MATCHES_ALL : "(.*)<FooBar>".toRegex(RegexOption.DOT_MATCHES_ALL)
groovy - 使用 (?s) 模式内修饰符 (demo):regex = /(?s)(.*)<FooBar>/
scala - 使用(?s) 修饰符(demo):"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
javascript - 使用[^] 或解决方法[\d\D] / [\w\W] / [\s\S] (demo):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>。 (注意:RegExp 对象的 MultiLine 属性有时被错误地认为是允许 . 跨换行符匹配的选项,而实际上,它只会更改 @987654464 @ 和 $ 行为匹配 lines 而不是 strings 的开始/结束,与 JavaScript 正则表达式相同)
行为。)
ruby - 使用/m MULTILINE modifier (demo):s[/(.*)<Foobar>/m, 1]
rtrebase-r - 基础 R PCRE 正则表达式 - 使用 (?s): regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2] (demo)
ricustringrstringi - 在由 ICU 正则表达式引擎驱动的 stringr/stringi 正则表达式函数中。也可以使用(?s):stringr::str_match(x, "(?s)(.*)<FooBar>")[,2](demo)
go - 在开头使用内联修饰符(?s) (demo):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
swift - 使用dotMatchesLineSeparators 或(更简单)将(?s) 内联修饰符传递给模式:let rx = "(?s)(.*)<Foobar>"
objective-c - 与 Swift 相同。 (?s) 工作最简单,但option can be used 是这样的:NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
re2、google-apps-script - 使用 (?s) 修饰符 (demo):"(?s)(.*)<Foobar>"(在 Google 电子表格中,=REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))
注意(?s):
在大多数非 POSIX 引擎中,(?s) 内联修饰符(或嵌入式标志选项)可用于强制 . 匹配换行符。
如果放在模式的开头,(?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] 被解析为匹配单个字符的括号表达式,\ 或 s 或 S。
【讨论】:
#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m 以反映这一点。并且仲裁器是 always 内联修饰符。 (?-sm)(?s).* 重置的位置。
. 匹配那里的任何字符(包括换行符)。见this online Bash demo。
如果您使用的是 Eclipse 搜索,您可以启用“DOTALL”选项来制作 '.'匹配任何字符,包括行分隔符:只需在搜索字符串的开头添加“(?s)”。示例:
(?s).*<FooBar>
【讨论】:
(?s) => (?m)的Ruby中。
在许多正则表达式方言中,/[\S\s]*<Foobar>/ 可以满足您的需求。 Source
【讨论】:
([\s\S]*)<FooBar>
点匹配除换行符 (\r\n) 之外的所有内容。所以使用 \s\S,它将匹配所有字符。
【讨论】:
[text rangeOfString:regEx options:NSRegularExpressionSearch],这将解决问题。谢谢!
<FooBar>
【讨论】:
s 而不是m?
我们也可以使用
(.*?\n)*?
匹配所有内容,包括换行符而不贪心。
这将使新行可选
(.*?|\n)*?
【讨论】:
(.*?|\n)*?,除非你想以灾难性的回溯结束。
"." 通常不匹配换行符。大多数正则表达式引擎允许您添加S-标志(也称为DOTALL 和SINGLELINE)以使"." 也匹配换行符。
如果失败,您可以执行[\S\s] 之类的操作。
【讨论】:
对于 Eclipse,以下表达式有效:
富
jadajada 酒吧"
正则表达式:
Foo[\S\s]{1,10}.*Bar*
【讨论】:
请注意,(.|\n)* 的效率可能低于(例如)[\s\S]*(如果您的语言的正则表达式支持此类转义),并且比查找如何指定使 .也匹配换行符。或者您可以使用 POSIXy 替代方案,例如 [[:space:][:^space:]]*。
【讨论】:
用途:
/(.*)<FooBar>/s
s 导致点 (.) 匹配回车符。
【讨论】:
s 标志存在于 PCRE 中,这是最完整的引擎(在 Perl 和 PHP 中可用)。 PCRE 有 10 个标志(以及许多其他功能),而 JavaScript 只有 3 个标志 (gmi)。
使用 RegexOptions.Singleline。它将. 的含义更改为包含换行符。
Regex.Replace(content, searchText, replaceText, RegexOptions.Singleline);
【讨论】:
在基于 Java 的正则表达式中,您可以使用 [\s\S]。
【讨论】:
s 标志添加到模式中,而 JavaScript 没有 s 标志。
一般来说,. 不匹配换行符,所以试试((.|\n)*)<foobar>。
【讨论】:
\r.:((?:.|\r?\n)*)<foobar>
使用模式修饰符sU 将在 PHP 中获得所需的匹配。
preg_match('/(.*)/sU', $content, $match);
【讨论】:
www.facebook.com(我已在hosts file 中阻止)。该链接是否损坏?
在语言中使用的上下文中,正则表达式作用于字符串,而不是行。所以你应该可以正常使用正则表达式,假设输入字符串有多行。
在这种情况下,给定的正则表达式将匹配整个字符串,因为存在“
基于行的正则表达式通常用于 egrep 之类的命令行。
【讨论】:
尝试:.*\n*.*<FooBar> 假设您也允许空白换行符。因为您允许任何字符,包括 <FooBar> 之前的任何字符。
【讨论】:
.*”?这可能适用于问题中的示例输入,但是如果“我遇到了同样的问题,并以可能不是最好的方式解决了它,但它确实有效。我在进行真正的比赛之前替换了所有换行符:
mystring = Regex.Replace(mystring, "\r\n", "")
我正在处理 HTML,所以在这种情况下,换行对我来说并不重要。
我尝试了上述所有建议,但没有成功。我正在使用 .NET 3.5 仅供参考。
【讨论】:
(\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>
【讨论】:
在notepad++中你可以使用这个
<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 在内的所有字符,直到.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>)。所以pattern和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
【讨论】: