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

问题描述 投票:280回答:21

例如,这个正则表达式

(.*)<FooBar>

将匹配:

abcde<FooBar>

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

abcde
fghij<FooBar>
regex multiline
21个回答
210
投票

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

/(.*)<FooBar>/s

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


7
投票

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

jadajada酒吧“

正则表达式:

SINGLELINE

5
投票
"."

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


4
投票

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


3
投票

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


3
投票

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

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


2
投票

解:

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

例:

(.|\n)*

资源:

[\s\S]* [[:space:][:^space:]]*


1
投票

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

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

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


1
投票

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

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

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

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


1
投票

0
投票

通常。与换行符不匹配,请尝试mystring= Regex.Replace(mystring, "\r\n", "")


297
投票

试试这个:

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

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


0
投票

我想匹配java中的特定if块

$("#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);
});

如果我使用regExp

<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>

它包括方法块的右括号,所以我用过

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

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


0
投票

通常我们必须修改一个子字符串,其中几个关键字分布在子字符串之前的行上。考虑一个xml元素:

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

   }
...
...
}

假设我们要修改81,到其他一些值,比如40.首先识别if \(isTrue(.|\n)*} ,然后跳过所有字符,包括if \(!isTrue([^}.]|\n)*} 直到<TASK> <UID>21</UID> <Name>Architectural design</Name> <PercentComplete>81</PercentComplete> </TASK> 。正则表达式模式和替换规范是:

.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

并且替换工作正常。


0
投票

通常在Powershell中搜索三个连续的行,它们看起来像:

(<PercentComplete>)

奇怪的是,这将是提示符下的unix文本,但是文件中的windows文本:

replaceSpec

这是打印行结尾的一种方法:

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

66
投票

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

(?s).*<FooBar>

58
投票

问题是,.模式可以匹配任何角色吗?答案因发动机而异。主要区别在于该模式是由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,基础R与perl=TRUE或用于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省略匹配到目前为止的文本,*?是一个懒惰的量词,(?=<Foobar>)匹配<Foobar>之前的位置。
  • - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" fileM允许文件在这里啜饮)。注意pcregrep是Mac OS grep用户的一个很好的解决方案。

See demos

基于非POSIX的引擎:

  • - 使用s修饰符PCRE_DOTALL modifierpreg_match('~(.*)<Foobar>~s', $s, $m)demo
  • - 使用RegexOptions.Singleline flag(demo): - 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]
  • qazxsw poi - 使用qazxsw poi修饰符(或者在开始时使用qazxsw poi在线版)():s
  • (?s) - 使用demo(或/(.*)<FooBar>/s)旗帜或内联修饰符(re.DOTALL):re.S(然后(?s)demo
  • m = re.search(r"(.*)<FooBar>", s, flags=re.S) - 使用if m:修饰符(或内联print(m.group(1))旗)():Pattern.DOTALL
  • (?s) - 使用demo in-pattern修饰符(Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)):
  • (?s) - 使用demo修饰符(regex = /(?s)(.*)<FooBar>/):
  • (?s) - 使用demo或变通办法"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) } / / [^][\d\D]):[\w\W]
  • [\s\S]demo)使用s.match(/([\s\S]*)<FooBar>/)[1]或JS解决方法():std::regex
  • [\s\S] - 使用与JavaScript相同的方法,demo
  • regex rex(R"(([\s\S]*)<FooBar>)"); - 使用([\s\S]*)<Foobar>):
  • /m MULTILINE modifier - 在开始时使用内联修饰符demos[/(.*)<Foobar>/m, 1]):
  • (?s) - 使用demo或(更简单)将re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)内联修饰符传递给模式:
  • dotMatchesLineSeparators - 与Swift相同,(?s)工作最简单,但这里是如何let rx = "(?s)(.*)<Foobar>"
  • (?s)option can be used - 使用NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];修饰符():(在Google Spreadsheets,(?s)

关于demo的说明:

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

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

POSIX说明:

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

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


31
投票

在JavaScript中,使用\s


27
投票

S

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


18
投票

在Ruby /[\S\s]*<Foobar>/中,您可以使用'Source'选项(多行):

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

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


11
投票

我们也可以使用

m

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

这将使新行可选

/YOUR_REGEXP/m

8
投票

the Regexp documentation通常与换行符不匹配。大多数正则表达式引擎允许您添加(.*?\n)*? -flag(也称为(.*?|\n)*? ".")以使S也匹配换行符。如果失败了,你可以做像DOTALL这样的事情。

© www.soinside.com 2019 - 2024. All rights reserved.