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

时间:2008-10-01 18:48:22

标签: regex multiline

例如,这个正则表达式

(.*)<FooBar>

将匹配:

abcde<FooBar>

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

abcde
fghij<FooBar>

24 个答案:

答案 0 :(得分:285)

试试这个:

((.|\n)*)<FooBar>

它基本上表示“任何字符或换行符”重复零次或多次。

答案 1 :(得分:202)

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

/(.*)<FooBar>/s

最后的 s 会使点匹配所有字符,包括换行符。

答案 2 :(得分:65)

如果您正在使用Eclipse搜索,则可以启用“DOTALL”选项来制作“。”匹配任何字符,包括行分隔符:只需在搜索字符串的开头添加“(?s)”。示例:

(?s).*<FooBar>

答案 3 :(得分:54)

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

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

关于的另一个注释:.默认匹配任何字符(demo):str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');tokens包含abcde\n fghij项目。)

此外,在所有的正则表达式语法中,默认情况下,点匹配换行符。 Boost的ECMAScript语法允许您使用regex_constants::no_mod_msource)将其关闭。

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

基于POSIX的引擎

仅仅.已经匹配换行符,无需使用任何修饰符,请参阅demo)。

demo),demo),(TRE,基本R默认引擎,没有perl=TRUE,对于带有perl=TRUE stringr / stringi 模式的基数R,请使用(?s)内联修饰符)(demo)同时处理{ {1}}以同样的方式。

然而,大多数基于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;};}' fileperl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"将整个文件放入内存,-0在应用-p给出的脚本后打印文件。请注意,使用-e会污染文件并激活“段落”模式&#39;其中Perl使用连续换行符(-000pe)作为记录分隔符。
  • - \n\n。在这里,grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file启用文件slurping,z启用(?s)模式的DOTALL模式,.启用不区分大小写的模式,(?i)省略到目前为止匹配的文本,\K是一个懒惰的量词,*?(?=<Foobar>)之前的位置匹配。
  • - <Foobar>pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file允许文件在这里啜饮)。注意M是Mac OS pcregrep用户的理想解决方案。

See demos

基于非POSIX的引擎

  • - 使用grep修饰符PCRE_DOTALL modifiersdemo
  • - 使用preg_match('~(.*)<Foobar>~s', $s, $m)标记(demo):
    - 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内嵌版本)(demo):(?s)
  • - 使用/(.*)<FooBar>/s(或re.DOTALL)个标记或re.S内联修饰符(demo):(?s)(然后{{ 1}},m = re.search(r"(.*)<FooBar>", s, flags=re.S)
  • - 使用if m:修饰符(或内联print(m.group(1))标记)(demo):Pattern.DOTALL
  • - 使用(?s) in-pattern修饰符(demo):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • - 使用(?s)修饰符(demo):regex = /(?s)(.*)<FooBar>/
  • - 使用(?s)或变通办法"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) } / [^] / [\d\D]demo):[\w\W]
  • [\s\S])使用s.match(/([\s\S]*)<FooBar>/)[1]或JS解决方法(demo):std::regex
  • - 使用与JavaScript [\s\S]相同的方法。
  • - 使用/m MULTILINE modifierdemo):regex rex(R"(([\s\S]*)<FooBar>)");
  • - 在开头使用内联修饰符([\s\S]*)<Foobar> demo):s[/(.*)<Foobar>/m, 1]
  • - 使用dotMatchesLineSeparators或(更简单)将(?s)内联修饰符传递给模式:re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • - 与Swift相同,(?s)最简单,但option can be usedlet rx = "(?s)(.*)<Foobar>"
  • 的方式如下
  • - 使用(?s)修饰符(demo):NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];(在Google Spreadsheets中,(?s)

关注"(?s)(.*)<Foobar>"

在大多数非POSIX引擎中,=REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")内联修饰符(或嵌入式标记选项)可用于强制(?s)匹配换行符。

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

POSIX note

在非正则表达式引擎中,要匹配任何字符,可以使用Delim1(?s:.*?)\nDelim2.* / .*? / .*构造。

在POSIX中,[\s\S]不匹配任何字符(如JavaScript或任何非POSIX引擎),因为括号表达式中不支持正则表达式转义序列。 [\d\D]被解析为与单个字符[\w\W][\s\S][\s\S]匹配的括号表达式。

答案 4 :(得分:31)

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

答案 5 :(得分:27)

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

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

答案 6 :(得分:18)

Ruby 中,您可以使用“m”选项(多行):

/YOUR_REGEXP/m

有关详细信息,请参阅ruby-doc.org上的the Regexp documentation

答案 7 :(得分:10)

我们也可以使用

(.*?\n)*?

匹配包括换行符在内的所有内容而无需贪婪

这将使新行为可选

(.*?|\n)*?

答案 8 :(得分:8)

"."通常与换行符不匹配。大多数正则表达式引擎允许您添加S - 标记(也称为DOTALLSINGLELINE),以使"."也匹配换行符。 如果失败,您可以执行[\S\s]

之类的操作

答案 9 :(得分:7)

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

  

     

jadajada Bar“

正则表达式:

Foo[\S\s]{1,10}.*Bar*

答案 10 :(得分:5)

/(.*)<FooBar>/s

s导致Dot(。)匹配回车

答案 11 :(得分:4)

在基于java的正则表达式中,您可以使用[\s\S]

答案 12 :(得分:3)

请注意,(.|\n)*的效率可能低于(例如)[\s\S]*(如果您的语言的正则表达式支持此类转义),而不是查找如何指定生成的修饰符。也匹配换行符。或者你可以使用像[[:space:][:^space:]]*这样的POSIXy替代品。

答案 13 :(得分:3)

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

Regex.Replace(content,searchText,replaceText,RegexOptions.Singleline);

答案 14 :(得分:2)

解决方案:

使用模式修饰符sU将在PHP中获得所需的匹配。

例如:

preg_match('/(.*)/sU',$content,$match);

来源:

http://dreamluverz.com/developers-tools/regex-match-all-including-new-line http://php.net/manual/en/reference.pcre.pattern.modifiers.php

答案 15 :(得分:1)

在语言中使用的上下文中,正则表达式作用于字符串,而不是行。所以你应该能够正常使用正则表达式,假设输入字符串有多行。

在这种情况下,给定的正则表达式将匹配整个字符串,因为“&lt; FooBar&gt;”存在。根据正则表达式实现的细节,$ 1值(从“(。*)”获得)将是“fghij”或“abcde \ nfghij”。正如其他人所说,一些实现允许您控制是否“。”将与换行符匹配,为您提供选择。

基于行的正则表达式通常用于像egrep这样的命令行。

答案 16 :(得分:1)

我遇到了同样的问题并且解决了它可能不是最好的方法,但它的工作原理。在我完成真正的比赛之前,我替换了所有换行符:

mystring= Regex.Replace(mystring, "\r\n", "")

我正在操纵HTML,所以在这种情况下换行并不重要。

我尝试了上述所有建议但没有运气,我正在使用.Net 3.5 FYI

答案 17 :(得分:1)

尝试:.*\n*.*<FooBar>假设您还允许使用空白换行符。因为您允许<FooBar>之前的任何字符都不能包含。

答案 18 :(得分:0)

通常我们必须修改一个子字符串,其中几个关键字分布在子字符串之前的行。考虑一个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>)。因此模式和replaceSpec也可以是:

pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")

并且替换工作正常。

答案 19 :(得分:0)

我想匹配java中的特定if块

   ...
   ...
   if(isTrue){
       doAction();

   }
...
...
}

如果我使用regExp

if \(isTrue(.|\n)*}

它包含方法块的右括号,所以我使用了

if \(!isTrue([^}.]|\n)*}

从通配符匹配中排除右括号。

答案 20 :(得分:0)

一般来说。与换行符不匹配,请尝试((.|\n)*)<foobar>

答案 21 :(得分:0)

在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&lt;Foobar&gt;</textarea>

答案 22 :(得分:0)

通常在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

答案 23 :(得分:-1)

选项1

一种方法是使用s标志(就像接受的答案一样):

/(.*)<FooBar>/s

Demo 1

选项2

第二种方法是使用m(多行)标志和以下任何一种模式:

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

/([\d\D]*)<FooBar>/m

/([\w\W]*)<FooBar>/m

Demo 2

RegEx电路

jex.im可视化正则表达式:

enter image description here