提问人:andyuk 提问时间:10/2/2008 最后编辑:Bobulousandyuk 更新时间:7/5/2023 访问量:991209
如何在正则表达式中的多行中匹配任何字符?
How do I match any character across multiple lines in a regular expression?
问:
例如,此正则表达式
(.*)<FooBar>
将匹配:
abcde<FooBar>
但是,如何让它在多行之间匹配呢?
abcde
fghij<FooBar>
答:
在语言中使用的上下文中,正则表达式作用于字符串,而不是行。因此,假设输入字符串有多行,您应该能够正常使用正则表达式。
在这种情况下,给定的正则表达式将与整个字符串匹配,因为存在“<FooBar>”。根据正则表达式实现的具体情况,$1 值(从 “(.*)” 获得)将为 “fghij” 或 “abcde\nfghij”。正如其他人所说,某些实现允许您控制“.”是否与换行符匹配,从而为您提供选择。
基于行的正则表达式通常用于命令行,例如 egrep。
这取决于语言,但应该有一个修饰符可以添加到正则表达式模式中。在PHP中,它是:
/(.*)<FooBar>/s
末尾的 s 使点匹配所有字符,包括换行符。
评论
s
[^]*
m
试试这个:
((.|\n)*)<FooBar>
它基本上说“任何字符或换行符”重复零次或多次。
评论
((.|\n|\r)*)<FooBar>
[\s\S]*
(?s).*
"."
通常与换行符不匹配。大多数正则表达式引擎允许您添加 -flag(也称为 和 )以使换行符也匹配。
如果失败了,你可以做类似的事情。S
DOTALL
SINGLELINE
"."
[\S\s]
通常,不匹配换行符,因此请尝试..
((.|\n)*)<foobar>
评论
\r
((?:.|\r?\n)*)<foobar>
用:
/(.*)<FooBar>/s
使点 (.) 与回车符匹配。s
评论
s
gmi
请注意,这可能比(例如)(如果你的语言的正则表达式支持这种转义)和找到如何指定使 .也匹配换行符。或者您可以使用 POSIXy 替代品,例如 .(.|\n)*
[\s\S]*
[[:space:][:^space:]]*
我遇到了同样的问题,并且可能以最好的方式解决了它,但它有效。在我进行真正的比赛之前,我替换了所有换行符:
mystring = Regex.Replace(mystring, "\r\n", "")
我正在操作 HTML,因此在这种情况下,换行符对我来说并不重要。
我尝试了上面的所有建议,但没有运气。我正在使用 .NET 3.5 仅供参考。
评论
(\s|\S)
(?s)
.
(\s|\S)
使用 RegexOptions.Singleline。它更改了包含换行符的含义。.
Regex.Replace(content, searchText, replaceText, RegexOptions.Singleline);
评论
我想匹配 Java 中的特定 if 块:
...
...
if(isTrue){
doAction();
}
...
...
}
如果我使用 regExp
if \(isTrue(.|\n)*}
它包括方法块的右大括号,所以我使用
if \(!isTrue([^}.]|\n)*}
从通配符匹配中排除右大括号。
在许多正则表达式方言中,会做你想做的事。源/[\S\s]*<Foobar>/
评论
如果您使用的是 Eclipse 搜索,您可以启用“DOTALL”选项,使 '.'' 匹配任何字符,包括行分隔符:只需在搜索字符串的开头添加 “(?s)” 即可。例:
(?s).*<FooBar>
评论
(?s)
=> (?m)
溶液:
使用模式修饰符将在 PHP 中获得所需的匹配。sU
例:
preg_match('/(.*)/sU', $content, $match);
来源:
评论
通常,我们必须修改一个子字符串,其中有几个关键字分布在子字符串前面的行中。考虑一个 XML 元素:
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>81</PercentComplete>
</TASK>
假设我们想将 81 修改为其他值,比如 40。首先识别 ,然后跳过所有字符,包括 till 。正则表达式模式和替换规范为:.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>)
replaceSpec
pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")
并且更换像以前一样正常工作。
评论
([\s\S]*)<FooBar>
该点匹配除换行符 () 之外的所有值。因此,请使用 ,它将匹配所有字符。\r\n
\s\S
评论
[text rangeOfString:regEx options:NSRegularExpressionSearch]
<FooBar>
在 Ruby 中,你可以使用 '' 选项(多行):m
/YOUR_REGEXP/m
有关详细信息,请参阅有关 ruby-doc.org 的正则表达式文档。
评论
s
m
对于 Eclipse,以下表达式有效:
傅
jadajada酒吧”
正则表达式:
Foo[\S\s]{1,10}.*Bar*
在基于 Java 的正则表达式中,可以使用 .[\s\S]
评论
s
s
问题是,图案可以匹配任何字符吗?答案因引擎而异。主要区别在于该模式是由 POSIX 还是非 POSIX 正则表达式库使用。.
关于 lua 模式的特别说明:它们不被视为正则表达式,但与那里的任何字符匹配,与基于 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 语法允许您使用 (source) 将其关闭。regex_constants::no_mod_m
至于 oracle(它是基于 POSIX 的),请使用 n
选项(演示):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,没有 R 的基本 R 默认引擎,对于带有 stringr/stringi 模式或用于 stringr/stringi 模式的基本 R,请使用内联修饰符) (demo) 也以同样的方式处理。perl=TRUE
perl=TRUE
(?s)
.
但是,大多数基于 POSIX 的工具会逐行处理输入。因此,与换行符不匹配,因为它们不在范围内。以下是一些如何覆盖此值的示例:.
- sed - 有多种解决方法。最精确但不是很安全的是(将文件放入内存中)。如果必须包含整行,则可以考虑(从开头删除将以包含匹配的行结束)或(排除匹配行)。
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 - ( 将整个文件放入内存中,在应用 给出的脚本后打印文件)。请注意,using 将删除文件并激活“段落模式”,其中 Perl 使用连续换行符 () 作为记录分隔符。
perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"
-0
-p
-e
-000pe
\n\n
- gnu-grep - .在这里,启用文件啃食,启用模式的 DOTALL 模式,启用不区分大小写模式,省略到目前为止匹配的文本,是一个惰性量词,匹配之前的位置。
grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file
z
(?s)
.
(?i)
\K
*?
(?=<Foobar>)
<Foobar>
- pcregrep - (在此处启用文件删除)。对于macOS用户来说,Note是一个很好的解决方案。
pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file
M
pcregrep
grep
查看演示。
非基于 POSIX 的引擎:
- php - 使用修饰符 PCRE_DOTALL 修饰符:(demo
s
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]
- perl - 使用修饰符(或开头的内联版本)(演示):
s
(?s)
/(.*)<FooBar>/s
- python - 使用(或)标志或内联修饰符(demo):(然后,
re.DOTALL
re.S
(?s)
m = re.search(r"(.*)<FooBar>", s, flags=re.S)
if m:
print(m.group(1))
) - java - 使用修饰符(或内联标志)(演示):
Pattern.DOTALL
(?s)
Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
- kotlin - 用途 :
RegexOption.DOT_MATCHES_ALL
"(.*)<FooBar>".toRegex(RegexOption.DOT_MATCHES_ALL)
- groovy - 使用模式修饰符(演示):
(?s)
regex = /(?s)(.*)<FooBar>/
- scala - 使用修饰符(演示):
(?s)
"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
- javascript - 使用
s
(dotAll
) 标志或解决方法 / / / (demo):[^]
[\d\D]
[\w\W]
[\s\S]
s.match(/([\s\S]*)<FooBar>/)[1]
- c++ () 使用或 JavaScript 解决方法(演示):
std::regex
[\s\S]
regex rex(R"(([\s\S]*)<FooBar>)");
- vba vbscript - 使用与 JavaScript 相同的方法。(注意:
RegExp
对象的属性有时被错误地认为是允许跨换行符匹配的选项,而实际上,它只是更改 和 行为以匹配行的开头/结尾而不是字符串,与 JavaScript 正则表达式相同)([\s\S]*)<Foobar>
MultiLine
.
^
$
- ruby - 使用
/m
MULTILINE 修饰符 (demo):s[/(.*)<Foobar>/m, 1]
- r trebase-r - Base R PCRE 正则表达式 - 使用:(demo
(?s)
regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]
) - r ICU stringrstringi - 由 ICU 正则表达式引擎提供支持的 IN / 正则表达式功能。也使用 : (demo
stringr
stringi
(?s)
stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]
) - go - 在开始时使用内联修饰符(演示):
(?s)
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 - 使用修饰符 (demo): (在 Google 电子表格中,
(?s)
"(?s)(.*)<Foobar>"
=REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")
)
关于(?s)
的说明:
在大多数非 POSIX 引擎中,内联修饰符(或嵌入式标志选项)可用于强制匹配换行符。(?s)
.
如果放在图案的开头,则更改图案中所有图案的 bahavior。如果 放在开始之后的某个地方,则只有位于其右侧的那些 s 会受到影响,除非这是传递给 Python 的 .在 Python 中,无论位置如何,整个模式都会受到影响。使用 停止效果。修改后的组可用于仅影响正则表达式模式的指定范围(例如,将跨换行符进行第一个匹配,而第二个将仅匹配行的其余部分)。(?s)
.
(?s)
.
re
re
(?s)
.
(?s)
(?-s)
Delim1(?s:.*?)\nDelim2.*
.*?
.*
POSIX说明:
在非 POSIX 正则表达式引擎中,为了匹配任何字符,可以使用 / / 构造。[\s\S]
[\d\D]
[\w\W]
在 POSIX 中,不匹配任何字符(如在 JavaScript 或任何非 POSIX 引擎中),因为括号表达式内不支持正则表达式转义序列。 解析为与单个字符或 或 匹配的括号表达式。[\s\S]
[\s\S]
\
s
S
评论
#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m
(?-sm)(?s).*
.
我们还可以使用
(.*?\n)*?
在不贪婪的情况下匹配包括换行在内的所有内容。
这将使新行成为可选行
(.*?|\n)*?
评论
(.*?|\n)*?
在 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>
通常在 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
选项 1
一种方法是使用标志(就像公认的答案一样):s
/(.*)<FooBar>/s
演示 1
选项 2
第二种方法是使用(多行)标志和以下任何模式:m
/([\s\S]*)<FooBar>/m
或
/([\d\D]*)<FooBar>/m
或
/([\w\W]*)<FooBar>/m
演示 2
正则表达式电路
jex.im 可视化正则表达式:
尝试:假设您也允许空换行符。由于您允许任何字符,因此之前没有包含任何字符。.*\n*.*<FooBar>
<FooBar>
评论
.*
在记事本++中,您可以使用此
<table (.|\r\n)*</table>
它将匹配整个表,从
行和列您可以使用以下方法使它贪婪,这样它就可以匹配第一个、第二个等表,而不是一次全部匹配
<table (.|\r\n)*?</table>
评论
(\r\n)*
- 超级答案。谢谢
这对我有用,是最简单的:
(\X*)<FooBar>
评论