476

例如,这个正则表达式

(.*)<FooBar>

将匹配:

abcde<FooBar>

但是如何让它跨多行匹配?

abcde
fghij<FooBar>
4

25 回答 25

532

试试这个:

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

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

于 2008-10-01T18:52:27.110 回答
287

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

/(.*)<FooBar>/s

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

于 2008-10-01T18:52:18.033 回答
147

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

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

的另一个说明:.默认情况下匹配任何字符(演示):(str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');包含tokens一个abcde\n fghij项目)。

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

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

基于 POSIX 的引擎

A.已经匹配换行符,因此不需要使用任何修饰符,请参阅 ( demo )。

( demo ), postgresql demo ) , (TRE, base R default engine with no perl=TRUE, 对于 base R with perl=TRUEor stringr / stringi模式,使用(?s)inline 修饰符) ( 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)。请注意, using-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>)" fileM在此处启用文件 slurping)。Notepcregrep对于 macOSgrep用户来说是一个很好的解决方案。

见演示

非基于 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)开头的内联版本)(demo):/(.*)<FooBar>/s

  • - 使用re.DOTALL(or re.S) 标志或(?s)内联修饰符 ( demo ): 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]或 JavaScript 变通办法 ( demo ):regex rex(R"(([\s\S]*)<FooBar>)");

  • - 使用与 JavaScript 相同的方法,([\s\S]*)<Foobar>. (注意:对象的MultiLine属性RegExp有时被错误地认为是允许.跨换行符匹配的选项,而实际上,它只会更改^and行为以匹配$的开始/结束而不是字符串,这与 JavaScript 中的相同正则表达式)行为。)

  • - 使用/m MULTILINE修饰符演示):s[/(.*)<Foobar>/m, 1]

  • - Base R PCRE 正则表达式 -使用(?s):(演示regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]

  • -由 ICU 正则表达式引擎驱动的输入stringr/正则表达式函数。stringi也可以使用(?s):(演示stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]

  • - 在开始时使用 inline 修饰符(?s)demo):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 电子表格中,=REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")

注意事项(?s)

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

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

POSIX 注释

在非 POSIX 正则表达式引擎中,要匹配任何字符,可以使用 // 构造[\s\S][\d\D][\w\W]

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

于 2017-08-31T12:47:20.463 回答
72

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

(?s).*<FooBar>
于 2011-11-25T13:16:55.893 回答
42

在许多正则表达式方言中,/[\S\s]*<Foobar>/会做你想做的事。来源

于 2011-07-30T13:03:56.440 回答
39

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

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

于 2012-07-19T17:59:45.447 回答
18

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

/YOUR_REGEXP/m

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

于 2012-08-03T07:52:16.613 回答
15

我们也可以使用

(.*?\n)*?

匹配所有内容,包括换行符而不贪心。

这将使新行可选

(.*?|\n)*?
于 2018-08-06T07:48:29.453 回答
9

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

于 2008-10-01T18:52:28.233 回答
8

对于 Eclipse,以下表达式有效:

贾达哈达酒吧"

正则表达式:

Foo[\S\s]{1,10}.*Bar*
于 2013-01-03T11:32:13.277 回答
5

采用:

/(.*)<FooBar>/s

导致点 ( . s) 匹配回车。

于 2008-10-01T18:54:07.980 回答
5

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

于 2008-10-02T03:31:26.990 回答
4

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

Regex.Replace(content, searchText, replaceText, RegexOptions.Singleline);
于 2010-04-13T00:42:03.950 回答
4

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

于 2013-06-03T06:22:19.503 回答
2

通常,.不匹配换行符,因此请尝试((.|\n)*)<foobar>.

于 2008-10-01T18:52:56.220 回答
2

解决方案:

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

例子:

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

资料来源:

于 2012-04-04T11:00:26.493 回答
1

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

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

基于行的正则表达式通常用于 egrep 之类的命令行。

于 2008-10-01T18:49:42.033 回答
1

我遇到了同样的问题,并以可能不是最好的方式解决了它,但它确实有效。在进行真正的比赛之前,我替换了所有换行符:

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

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

我尝试了上面的所有建议,但没有运气。我正在使用 .NET 3.5 仅供参考。

于 2009-03-26T14:57:08.103 回答
1

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

于 2019-02-27T12:50:43.143 回答
1

尝试:.*\n*.*<FooBar>假设您也允许空白换行符。因为您允许任何字符,包括之前的任何内容<FooBar>

于 2020-08-28T16:21:39.570 回答
1

在记事本++中,您可以使用它

<table (.|\r\n)*</table>

它将匹配整个表从

行和列

您可以使用以下方法使其变得贪婪,这样它将匹配第一个、第二个等表,而不是一次全部匹配

<table (.|\r\n)*?</table>
于 2022-01-29T02:28:34.463 回答
0

我想在 Java中匹配一个特定的if块:

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

   }
...
...
}

如果我使用正则表达式

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

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

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

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

于 2011-01-18T09:31:21.063 回答
0

通常,我们必须使用分布在子字符串前面的行中的几个关键字来修改子字符串。考虑一个 XML 元素:

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>81</PercentComplete>
</TASK>

假设我们想将 81 修改为其他值,比如 40。首先确定.UID.21..UID.,然后跳过包括\nuntil在内的所有字符.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")

并且更换工作正常。

于 2012-04-21T20:05:32.873 回答
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
于 2019-07-05T14:12:02.540 回答
-1

选项1

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

/(.*)<FooBar>/s

演示 1

选项 2

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

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

或者

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

或者

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

演示 2

正则表达式电路

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

在此处输入图像描述

于 2019-10-06T19:41:28.093 回答