正则表达式匹配任意字符,包括换行符

340

有没有一种正则表达式可以匹配“包括换行符在内的所有字符”?

例如,在下面的正则表达式中,$2 没有输出,因为 (.+?) 在匹配时不包括换行符。

$string = "START Curabitur mollis, dolor ut rutrum consequat, arcu nisl ultrices diam, adipiscing aliquam ipsum metus id velit. Aenean vestibulum gravida felis, quis bibendum nisl euismod ut. 

Nunc at orci sed quam pharetra congue. Nulla a justo vitae diam eleifend dictum. Maecenas egestas ipsum elementum dui sollicitudin tempus. Donec bibendum cursus nisi, vitae convallis ante ornare a. Curabitur libero lorem, semper sit amet cursus at, cursus id purus. Cras varius metus eu diam vulputate vel elementum mauris tempor. 

Morbi tristique interdum libero, eu pulvinar elit fringilla vel. Curabitur fringilla bibendum urna, ullamcorper placerat quam fermentum id. Nunc aliquam, nunc sit amet bibendum lacinia, magna massa auctor enim, nec dictum sapien eros in arcu. 

Pellentesque viverra ullamcorper lectus, a facilisis ipsum tempus et. Nulla mi enim, interdum at imperdiet eget, bibendum nec END";

$string =~ /(START)(.+?)(END)/;

print $2;

1
你可能想了解正则表达式修饰符/标志,例如:m,s(m / regex / ims ...) - snoofkin
7个回答

456

如果您不想添加/s正则表达式修饰符(也许您仍希望在正则表达式的其他地方保留.的原始含义),您也可以使用字符类。一种可能性是:

[\S\s]

一个既不是空格也是空格的字符。换句话说,任何字符都可以。

您还可以在正则表达式的一小部分中局部更改修饰符,例如:

(?s:.)

6
我马上要加入使用(?s:.)语法的讨论。+1 - BoltClock
1
除了不够优雅之外,(?:.|\n) 有什么劣势吗? - Vlastimil Ovčáčík
9
“[\S\s]+” 是我正在寻找的内容。谢谢。+1 - Ryan
1
@VlastimilOvčáčík 如果你在使用*+时,它可能会对运行时非常糟糕,因为它有2^n种不同的方式可以匹配任何给定长度为n的字符串。 - Radon Rosborough

254

在你的正则表达式中添加s修饰符,使.与换行符匹配:

$string =~ /(START)(.+?)(END)/s;

42
在 JavaScript 中:(START)[\s\S]*(END) - 访问 www.regexpal.com 进行测试 - Zymotik
1
有关@Zymotik评论的更多信息,请参见:https://dev59.com/4XNA5IYBdhLWcg3wKacx - Jacob van Lingen
3
在Java中,您可以在正则表达式的开头使用内联修饰符(?s),例如要替换'yourPattern'后面包括换行符在内的任何字符,请使用"(?s)yourPattern.*"- 另请参见:https://www.rexegg.com/regex-modifiers.html#dotall - LukeSolar
在Ruby中,修饰符是m,而不是s。参见:https://rubular.com/ - Jon Schneider
JavaScript现在支持这种方式。ES2018添加了s dotAll标志。 - Lyall

26
这对我来说非常易读,并且与"任何字符或换行符"匹配
(.|\n)*

它的行为与之相同
[\S\s]*

和一样

(?s:.)*

此外,您还可以在末尾添加一个问号?来使正则表达式变得贪婪(在第一次匹配时停止)(.|\n)*?
// Eager (stop on first match)
start_string(.|\n)*?end_string

否则只有(.|\n)*正则表达式是贪婪的,你可能会得到多个end_string:

start_string some text
and newlines end_string
some more text end_string

10

没错,你只需要让.匹配换行符:

$string =~ /(START)(.+?)(END)/s;

0
我喜欢使用一个空的否定集合,它可以匹配任何不在该组中的字符,因为它是空的,所以它可以匹配包括换行符在内的任何内容。
[^]

如果你想要超过零个字符
[^]*

或者多个
[^]+

在JavaScript中进行测试。


不确定这个。你使用的是哪个具体的正则表达式引擎实现?我认为这种表示法没有常规或广泛采用的含义。例如,Notepad++会拒绝这个表达式,因为它是格式错误的。一个问题是,如果引擎不能假设在(否定的)集合中至少有一个字符,那么你将不得不建立另一个转义序列来否定一个单独的']'字符的集合。 - Glenn Slayden
我正在使用Chrome(V8),如果我在控制台中粘贴/[^]*/.test('whatever'),它会返回true - Ayo Reis

-1
跟其他答案一起使用/s标志,让.匹配每个字符。 Perl v5.12添加了\N作为字符类的快捷方式,以便始终匹配除换行符之外的任何字符,而不管/s的设置如何。这使得\n可以像\s\S那样有一个伴侣。
有了这个,你可以像其他类似的答案一样使用补集的两边:[\n\N][\s\S]等等。
然而,你还标记了这个问题为javascript,它认为\N只是大写字母N。

-6

你想使用“多行文本”。

$string =~ /(START)(.+?)(END)/m;

8
不,m 影响 ^$ 锚点,但不影响 . - BoltClock
有趣,谢谢。我猜我从来没有尝试过完全按照OP所要求的去做。 - nadime

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接