如何在多行中使用JavaScript正则表达式?


275
var ss= "<pre>aaaa\nbbb\nccc</pre>ddd";
var arr= ss.match( /<pre.*?<\/pre>/gm );
alert(arr);     // null

我希望可以拾取PRE块,即使它跨越换行符也是如此。我以为'm'标志可以做到。才不是。

发布前在这里找到答案。因为我以为我知道JavaScript(读了三本书,工作了几个小时),并且SO上没有现有的解决方案,所以无论如何我都敢发表。在这里扔石头

所以解决方案是:

var ss= "<pre>aaaa\nbbb\nccc</pre>ddd";
var arr= ss.match( /<pre[\s\S]*?<\/pre>/gm );
alert(arr);     // <pre>...</pre> :)

有人有没有那么神秘的方式?

编辑:是重复的,但是由于它比我的更难找到,因此我不会删除。

它建议[^]作为“多行点”。我仍然不明白的是为什么[.\n]不起作用。猜猜这是JavaScript的可悲部分之一。


29
不太神秘的正则表达式?本质上不可能。
鲁本斯·法里亚斯

顺便说一句,您应该阅读:“解析HTML:克苏鲁之路” codinghorror.com/blog/archives/001311.html
Rubens Farias

1
链接从以前的评论更改了:blog.codinghorror.com/parsing-html-the-cthulhu-way(5年后)
dab

Answers:


248

[.\n]因为.里面没有特殊的含义而不起作用[],只是表示文字.(.|\n)将是一种指定“任何字符,包括换行符”的方法。如果要匹配所有换行符,则还需要添加\r以包括Windows和经典Mac OS样式的行尾(.|[\r\n])

事实证明这比较麻烦且缓慢(请参阅KrisWebDev的答案以获取详细信息),因此更好的方法是使用匹配所有空白字符和所有非空白字符[\s\S],这将匹配所有内容,并且速度更快且更简单。

通常,您不应该尝试使用正则表达式来匹配实际的HTML标签。例如,请参阅这些 问题以获取有关原因的更多信息。

相反,请尝试实际在DOM中搜索所需标签(使用jQuery可以简化此操作,但您始终可以document.getElementsByTagName("pre")使用标准DOM),然后如果需要与内容匹配,则使用regexp搜索这些结果的文本内容。


我正在做的是使用JavaScript动态地进行.wiki-> HTML转换。因此,我还没有可用的DOM。Wiki文件主要是其自身的语法,但是如果需要,我允许使用HTML标记。如果我正在处理DOM,您的建议非常有效。谢谢。:)
akauppi'1

很公平。我想这是在HTML上使用正则表达式的正当理由,尽管与HTML混合的Wiki语法本身可能具有各种有趣的特例。
布莱恩·坎贝尔

2
[\r\n]应用于序列\ r \ n,将首先匹配\ r,然后匹配\ n。如果您想一次匹配整个序列,无论该序列是\ r \ n还是只是\ n,请使用模式.|\r?\n
Eirik Birkeland

1
要匹配整个多行字符串,请尝试greedy [\s\S]+
波阿斯

我只想补充一下,忽略.内部含义的JS正则表达式语法与其他正则表达式框架(特别是.NET中的高级正则框架[]不同。人们,请不要以为正则表达式是跨平台的,它们经常不是
TA先生

330

不要使用(.|[\r\n])代替.多行匹配。

[\s\S]不要使用代替.多行匹配

另外,在不需要的地方,请使用*?+?而不是*或来避免贪婪+。这会对性能产生巨大影响。

请参阅我的基准测试:http : //jsperf.com/javascript-multiline-regexp-workarounds

Using [^]: fastest
Using [\s\S]: 0.83% slower
Using (.|\r|\n): 96% slower
Using (.|[\r\n]): 96% slower

注意:您也可以使用,[^]但以下注释已弃用。


22
好点,但我还是建议不要使用[^]。一方面,JavaScript是我所知道的唯一支持该惯用语的语言,即使在那里,使用它的频率也很少[\s\S]。另一方面,大多数其他口味可让您]通过先列出来逃脱。换句话说,在JavaScript中[^][^]的任意两个字符匹配,但在.NET它匹配任何一个不是字符等][^
艾伦·摩尔

1
你怎么知道这\S将匹配\r\n与其他字符?
吉利2013年

3
有关\ s \ S详细信息,请参见此问题。这是一种匹配所有空白字符+所有非空白字符=所有字符的技巧。有关regexp特殊字符文档,另请参见MDN
KrisWebDev

4
任何理由,更喜欢[\s\S]过别人,喜欢[\d\D]还是[\w\W]
Phrogz

1
让我快速指出,您对贪婪运算符的测试已被操纵。/<p>Can[^]*?<\/p>/与的内容不匹配/<p>Can[^]*<\/p>/。贪婪变体应更改/<p>(?:[^<]|<(?!\/p>))*<\/p>/为匹配相同的内容。
3limin4t0r

19

您没有指定您的环境和Javascript(ECMAscript)版本,我意识到这篇文章来自2009年,但是为了完整起见,随着ECMA2018的发布,我们现在可以使用该s标志.来匹配“ \ n”,请参见https ://stackoverflow.com/a/36006948/141801

从而:

let s = 'I am a string\nover several\nlines.';
console.log('String: "' + s + '".');

let r = /string.*several.*lines/s; // Note 's' modifier
console.log('Match? ' + r.test(s); // 'test' returns true

这是最新添加的功能,在许多当前环境中均无法使用,例如Node v8.7.0似乎无法识别它,但它在Chromium中可以使用,我正在编写的Typescript测试中使用它,大概是随着时间的流逝,它将变得更加主流。


1
这在Chrome浏览器(v67)中效果很好,但在IE11和IEdge(v42)中完全破坏了正则表达式(也停止逐行工作)
自由开放时间

谢谢@freedomn -m .. IE不支持一项非常新的功能几乎是不足为奇的:)但是,是的,值得一提的是它无法保存任何试图“调试”他们尝试使用该功能的人不起作用的方法如预期的那样。
NEEK

11

[.\n]不起作用,因为点号[](按正则表达式定义;并非仅适用于javascript)表示点号字符。您可以改用(.|\n)(或(.|[\n\r]))。


24
[\s\S]是用于匹配包括换行符在内的所有内容的最常见的JavaScript习惯用法。与像的基于交替的方法相比,它在眼睛上更容易且效率更高(.|\n)。(它的字面意思是“任何字符空格或任何字符不是空格。)
艾伦·摩尔

2
您是对的,但问题是关于.\n,为什么[.\n]不起作用。正如问题中提到的,这[^]也是一种不错的方法。
Y. Shoham

6

我已经对其进行了测试(Chrome),[^]并且[^\0]通过(或.)更改点()对它(以及和)都有效,因为点与换行符不匹配(请参见此处:[^\0][^]http://www.regular-expressions.info/dot.html)。

var ss= "<pre>aaaa\nbbb\nccc</pre>ddd";
var arr= ss.match( /<pre[^\0]*?<\/pre>/gm );
alert(arr);     //Working


1
问题[^\0]在于即使Javascript字符串中允许使用空字符,它也不会匹配空字符(请参阅此答案)。
唐老鸭

0

除了上述示例,它是替代的。

^[\\w\\s]*$

\w单词在哪里\s,空格在哪里

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.