如何在正则表达式中跨多行匹配任何字符?

and*_*yuk 315 regex multiline

例如,这个正则表达式

(.*)<FooBar>
Run Code Online (Sandbox Code Playgroud)

将匹配:

abcde<FooBar>
Run Code Online (Sandbox Code Playgroud)

但是如何让它在多行中匹配呢?

abcde
fghij<FooBar>
Run Code Online (Sandbox Code Playgroud)

lev*_*vik 318

试试这个:

((.|\n)*)<FooBar>
Run Code Online (Sandbox Code Playgroud)

它基本上说"任何字符或换行符"重复零次或多次.

  • 根据您的行结尾,您可能需要`((.| \n |\r)*)<FooBar>` (35认同)
  • 这是匹配多行输入的最差正则表达式.除非您使用ElasticSearch,否则请不要使用它.使用`[\ s\S]*`或`(?s).*`. (11认同)
  • 对 - 问题是关于日食,标签也是如此.但是,公认的解决方案是PHP解决方案.你的应该是公认的解决方案...... (4认同)
  • 在某些情况下,这种不必要的交替可能会导致灾难性的回溯。这不是一个好的通用模式。 (4认同)
  • @PeterMortensen 太多人已经报告了使用此模式时的性能问题,甚至堆栈溢出错误,我什至录制了一个 [YT 视频](https://www.youtube.com/watch?v=SEobSs-ZCSE)解释为什么这么糟糕。 (4认同)
  • 这取决于您使用的语言和/或工具.请告诉我们您使用的是什么,例如Perl,PHP,CF,C#,sed,awk等. (3认同)
  • 他说他正在使用Eclipse.在我看来,这是正确的解决方案.我有同样的问题,这解决了它. (3认同)
  • `\R` 以与平台无关的方式匹配行结尾。至少在 Eclipse 和其他一些工具中是这样。 (2认同)

Jer*_*ten 223

这取决于语言,但应该有一个可以添加到正则表达式模式的修饰符.在PHP中它是:

/(.*)<FooBar>/s
Run Code Online (Sandbox Code Playgroud)

最后的s使得点匹配包括换行符在内的所有字符.

  • @Allen - JavaScript不支持`s`修饰符.相反,为了相同的效果做`[^]*`. (6认同)
  • s标志(现在?)无效,至少在Chrome/V8中是这样.而是使用/([\ s\S]*)<FooBar> /字符类(匹配空格和非空格)而不是句点匹配器.有关详细信息,请参阅其他答案. (4认同)
  • @Grace:使用\n来匹配换行符 (3认同)
  • 在 Ruby 中,使用 `m` 修饰符 (2认同)

Wik*_*żew 71

问题是,可以.模式匹配任何字符吗?答案因发动机而异.主要区别在于该模式是由POSIX还是非POSIX正则表达式库使用.

关于特别说明:它们不被视为正则表达式,但.匹配任何char,与基于POSIX的引擎相同.

在另一方面:在.匹配默认(任何字符演示): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');(tokensabcde\n fghij项目).

此外,在所有的正则表达式语法中,默认情况下,点匹配换行符.Boost的ECMAScript语法允许你用regex_constants::no_mod_m()关闭它.

至于(基于POSIX),使用n选项(demo):select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

基于POSIX的引擎:

仅仅.已经匹配换行符,不需要使用任何修饰符,请参阅(演示).

(演示),(演示),(TRE,基础R没有默认设置引擎perl=TRUE,用于与基础R perl=TRUEstringr/stringi图案,使用(?s)内联改性剂)(演示)也可治疗.相同的方式.

但是,大多数基于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将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允许文件在这里).注意pcregrep是Mac OS grep用户的一个很好的解决方案.

看演示.

基于非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)开头的内联版本)(演示):/(.*)<FooBar>/s
  • - 使用re.DOTALL(或re.S)标志或(?s)内联修饰符(演示):( m = re.search(r"(.*)<FooBar>", s, flags=re.S)然后if m:,print(m.group(1)))
  • - 使用Pattern.DOTALL修饰符(或内联(?s)标志)(演示):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • - 使用(?s)模式内修饰符(演示):regex = /(?s)(.*)<FooBar>/
  • - 使用(?s)修饰符(演示):"(?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变通方法(演示):regex rex(R"(([\s\S]*)<FooBar>)");
  • - 使用与JavaScript相同的方法([\s\S]*)<Foobar>.
  • - 使用/m MULTILINE修饰符(演示):s[/(.*)<Foobar>/m, 1]
  • - (?s)在开始时使用内联修饰符(演示):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • - 使用dotMatchesLineSeparators或(更简单)将(?s)内联修饰符传递给模式:let rx = "(?s)(.*)<Foobar>"
  • - 与Swift相同,(?s)工作最简单,但这里是如何使用该选项:NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • ,- 使用(?s)修饰符(演示):( "(?s)(.*)<Foobar>"在Google Spreadsheets中=REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))

注意事项(?s):

在大多数非POSIX引擎中,(?s)可以使用内联修饰符(或嵌入式标记选项)来强制.匹配换行符.

如果放置在模式的开头,则(?s)更改模式中所有.的行为.如果(?s)它位于开头之后的某个位置,那么只有.位于其右侧的那些会受到影响,除非这是传递给Python的模式re.在Python中re,无论(?s)位置如何,整个模式都会.受到影响.该(?s)效果被停止使用(?-s).修改后的组可用于仅影响正则表达式模式的指定范围(例如,Delim1(?s:.*?)\nDelim2.*.*?跨越换行符进行第一次匹配,而第二次.*匹配将仅匹配行的其余部分).

POSIX说明:

在非正则表达式引擎中,为了匹配任何char,可以使用[\s\S]/ [\d\D]/ [\w\W]构造.

在POSIX中,[\s\S]不匹配任何char(如在JavaScript或任何非POSIX引擎中),因为括号表达式中不支持正则表达式转义序列.[\s\S]被解析为匹配单个字符,即方括号表达式\sS.

  • 您应该从您的个人资料页面链接到这个优秀的概述(+1). (5认同)
  • @PasupathiRajamanickam Bash使用POSIX正则表达式引擎,`.`匹配那里的任何字符(包括换行符).参见[此在线Bash演示](https://ideone.com/d1XTpR). (2认同)

Pau*_*son 66

如果您正在使用Eclipse搜索,则可以启用"DOTALL"选项以生成"." 匹配任何字符,包括行分隔符:只需在搜索字符串的开头添加"(?s)".例:

(?s).*<FooBar>
Run Code Online (Sandbox Code Playgroud)

  • 这不是eclipse特定的,应该在任何地方工作. (10认同)

小智 35

在JavaScript中,使用/[\S\s]*<Foobar>/.资源

  • 从该链接:"JavaScript和VBScript没有选项使点匹配换行符.在这些语言中,您可以使用[\ s\S]等字符类来匹配任何字符." 而不是.使用[\ s\S](匹配空格和非空格)代替. (2认同)

sam*_*ize 28

([\s\S]*)<FooBar>

该点匹配除换行符之外的所有内容(\ r \n).所以使用\ s\S,它将匹配所有字符.

  • 这适用于 intelliJ 的查找和替换正则表达式,谢谢。 (2认同)

小智 18

Ruby 您可以使用' m'选项(多行):

/YOUR_REGEXP/m
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅ruby-doc.org上的Regexp文档.


Nam*_*915 13

我们也可以使用

(.*?\n)*?
Run Code Online (Sandbox Code Playgroud)

匹配一切,包括没有贪婪的换行

这将使新行可选

(.*?|\n)*?
Run Code Online (Sandbox Code Playgroud)


Mar*_*rot 8

"."通常不符合换行符.大多数正则表达式引擎允许您添加S-flag(也称为DOTALLSINGLELINE)以使"."匹配换行符.如果失败了,你可以做类似的事情[\S\s].


小智 7

对于Eclipse,使用以下表达式:

jadajada酒吧"

正则表达式:

Foo[\S\s]{1,10}.*Bar*
Run Code Online (Sandbox Code Playgroud)


Mat*_*ski 7

这对我有用,并且是最简单的:

(\X*)<FooBar>
Run Code Online (Sandbox Code Playgroud)


Ham*_*han 6

在记事本++中你可以使用这个

<table (.|\r\n)*</table>
Run Code Online (Sandbox Code Playgroud)

它将匹配从以下位置开始的整个表

行和列

您可以使用以下命令使其变得贪婪,这样它将匹配第一个、第二个等表,而不是同时匹配所有表

<table (.|\r\n)*?</table>
Run Code Online (Sandbox Code Playgroud)


Bil*_*ill 5

/(.*)<FooBar>/s
Run Code Online (Sandbox Code Playgroud)

s导致Dot(.)匹配回车符


tye*_*tye 5

请注意,这(.|\n)*可能比(例如)[\s\S]*(如果您的语言的正则表达式支持此类转义)和查找如何指定使 . 也匹配换行符。或者您可以使用 POSIXy 替代品,例如[[:space:][:^space:]]*.


小智 5

使用 RegexOptions.Singleline。.它改变了包含换行符的含义。

Regex.Replace(content, searchText, replaceText, RegexOptions.Singleline);
Run Code Online (Sandbox Code Playgroud)