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

Posted

技术标签:

【中文标题】如何在多行上使用 JavaScript 正则表达式?【英文标题】:How to use JavaScript regex over multiple lines? 【发布时间】:2010-12-31 02:16:56 【问题描述】:
var ss= "<pre>aaaa\nbbb\nccc</pre>ddd";
var arr= ss.match( /<pre.*?<\/pre>/gm );
alert(arr);     // null

我希望 PRE 块被拾取,即使它跨越换行符。我认为'm'标志可以做到这一点。没有。

在发帖前找到答案here。因为我认为我知道 javascript(阅读三本书,工作时间)并且在 SO 没有现有的解决方案,所以我还是敢于​​发布。 在这里扔石头

所以解决办法是:

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

有没有人有不那么神秘的方法?

编辑:this 是重复的,但因为它比我的更难找到,所以我不删除。

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

【问题讨论】:

一个不那么神秘的正则表达式?自然不可能。 顺便说一句,您应该阅读:“解析 html:克苏鲁之道”codinghorror.com/blog/archives/001311.html 链接从之前的评论更改:blog.codinghorror.com/parsing-html-the-cthulhu-way(5 年后) 【参考方案1】:

不要使用(.|[\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

注意:您也可以使用[^],但在下面的评论中已弃用。

【讨论】:

好点,但我还是建议不要使用[^]。一方面,JavaScript 是我所知道的唯一支持该习惯用法的风格,即使在那里,它的使用频率也远不及 [\s\S]。另一方面,大多数其他风格可以让您通过首先列出 ] 来逃避它。换句话说,在 JavaScript 中,[^][^] 匹配任意两个字符,但在 .NET 中,它匹配除 ][^ 之外的任何 one 字符。 你怎么知道\S 将匹配\r\n 与其他字符? 请参阅 this question 了解 \s\S 详细信息。这是匹配所有空白字符 + 所有非空白字符 = 所有字符的 hack。另请参阅 MDN 获取正则表达式特殊字符文档。 有什么理由比其他人更喜欢[\s\S],比如[\d\D][\w\W] 让我快速指出您对贪婪运算符的测试是被操纵的。 /&lt;p&gt;Can[^]*?&lt;\/p&gt;//&lt;p&gt;Can[^]*&lt;\/p&gt;/ 的内容不匹配。贪婪的变种应该改成/&lt;p&gt;(?:[^&lt;]|&lt;(?!\/p&gt;))*&lt;\/p&gt;/来匹配相同的内容。【参考方案2】:

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

事实证明这有点麻烦,而且速度很慢(请参阅KrisWebDev's answer for details),因此更好的方法是匹配所有空白字符和所有非空白字符,[\s\S],它将匹配所有内容,并且更快更简单。

一般来说,您不应该尝试使用正则表达式来匹配实际的 HTML 标记。例如,请参阅thesequestions,了解有关原因的更多信息。

相反,尝试在 DOM 中实际搜索您需要的标签(使用 jQuery 使这更容易,但您始终可以使用标准 DOM 执行document.getElementsByTagName("pre")),然后使用正则表达式搜索这些结果的文本内容,如果您需要与内容相匹配。

【讨论】:

我正在做的是使用 JavaScript 即时进行 .wiki -> HTML 转换。因此,我还没有可用的 DOM。 Wiki 文件主要是它自己的语法,但如果需要,我允许使用 HTML 标记。如果我正在处理 DOM,您的建议是非常有效的。谢谢。 :) 很公平。我想这是想在 HTML 上使用正则表达式的正当理由,尽管与 HTML 混合的 wiki 语法本身可以有各种有趣的极端情况。 [\r\n]应用于序列\r\n,将首先匹配\r,然后匹配\n。如果您想一次匹配整个序列,无论该序列是 \r\n 还是只是 \n,请使用模式 .|\r?\n 要匹配一个整个多行字符串,试试贪婪的[\s\S]+ 我只想为后人补充一点,忽略[]. 含义的JS 正则表达式语法与其他正则表达式框架不同,尤其是.网。各位,请不要假设正则表达式是跨平台的,它们通常不是!!【参考方案3】:

您没有指定您的环境和 Javascript (ECMAscript) 版本,我知道这篇文章是从 2009 年开始的,但只是为了完整起见,随着 ECMA2018 的发布,我们现在可以使用 s 标志来导致 .要匹配 '\n',请参阅 https://***.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 测试中使用它随着时间的推移,它可能会变得更加主流。

【讨论】:

这在 Chrome (v67) 中效果很好,但在 IE11 和 IEdge(v42) 中完全破坏了正则表达式(也停止逐行工作) 谢谢@freedomn-m .. IE 不支持一个非常新的功能几乎完全不足为奇 :) 但是是的,值得一提的是,它无法拯救任何试图“调试”的人为什么他们的尝试使用它没有按预期工作。【参考方案4】:

[.\n] 不起作用,因为[] 中的点(通过正则表达式定义;不仅限于javascript)表示点字符。您可以改用(.|\n)(或(.|[\n\r]))。

【讨论】:

[\s\S] 是最常见的 JavaScript 习惯用法,用于匹配包括换行符在内的所有内容。它比(.|\n) 之类的基于交替的方法更容易看,效率更高。 (字面意思是“任何空格的字符或任何不是空格的字符。) 你是对的,但问题是关于.\n,以及为什么[.\n] 不起作用。如问题中所述,[^] 也是不错的方法。【参考方案5】:

我已经测试过它(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

【讨论】:

[^\0] 的问题在于它不会匹配空字符,即使 Javascript 字符串中允许使用空字符(请参阅this answer)。【参考方案6】:

现在有了 s(单行)修饰符,它可以让点也匹配新行 :) \s 也将匹配新行:D

在斜线后面加s

 /<pre>.*?<\/pre>/gms

【讨论】:

这是正确的答案,IMO\【参考方案7】:

除了上述例子之外,它是一个替代品。

^[\\w\\s]*$

\w 用于单词,\s 用于空格

【讨论】:

【参考方案8】:

[\\w\\s]*

这个对我来说太有用了,尤其是在匹配包括新行在内的多个内容时,每个其他答案最终都只是将所有匹配项组合在一起。

【讨论】:

以上是关于如何在多行上使用 JavaScript 正则表达式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript 中将长正则表达式拆分为多行?

多行格式化的 JavaScript 正则表达式 [重复]

javascript 正则表达式的使用

JavaScript 正则表达式详细分析

在多行上使用正则表达式进行 Html 解析

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