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

IT技术 javascript regex
2021-02-08 21:11:21
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 的可悲部分之一。

6个回答

不要使用(.|[\r\n]),而不是.多行匹配。

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

此外,通过使用*?+?量词代替*or来避免不需要的贪婪+这会对性能产生巨大的影响。

请参阅我所做的基准测试: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

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

让我快速指出您对贪婪运算符的测试被操纵了。/<p>Can[^]*?<\/p>/与 不匹配相同的内容/<p>Can[^]*<\/p>/贪婪变体应更改为/<p>(?:[^<]|<(?!\/p>))*<\/p>/以匹配相同的内容。
2021-04-05 21:11:21
好点,但我建议不要使用[^]一方面,JavaScript 是我所知道的唯一一种支持该习惯用法的风格,即使在那里,它的使用频率也不如[\s\S]. 另一方面,大多数其他口味让您]通过首先列出它来逃避换句话说,在JavaScript中[^][^]的任意两个字符匹配,但在.NET它匹配任何一个不是字符等][^
2021-04-08 21:11:21
有什么理由更喜欢[\s\S]其他人,喜欢[\d\D][\w\W]
2021-04-08 21:11:21
你怎么知道这\S将匹配\r\n对抗其他一些字符?
2021-04-09 21:11:21
有关\s\S 的详细信息,请参阅此问题这是匹配所有空白字符 + 所有非空白字符 = 所有字符的技巧。另请参阅MDN以获取正则表达式特殊字符文档。
2021-04-09 21:11:21

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

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

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

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

很公平。我想这是想在 HTML 上使用正则表达式的正当理由,尽管与 HTML 混合的 wiki 语法本身可以有各种有趣的极端情况。
2021-03-25 21:11:21
[\r\n]应用于序列\r\n,将首先匹配\r,然后匹配\n。如果您想一次匹配整个序列,无论该序列是 \r\n 还是只是 \n,请使用模式.|\r?\n
2021-03-25 21:11:21
要匹配整个多行字符串,请尝试使用 greedy [\s\S]+
2021-03-26 21:11:21
我只想补充留给后人的是JS正则表达式语法忽视的意义.[]不同的比其他的正则表达式框架,特别是先进的一个在.NET。人们,请不要假设正则表达式是跨平台的,它们经常不是!!
2021-03-30 21:11:21
我正在做的是使用 JavaScript 即时进行 .wiki -> HTML 转换。因此,我还没有可用的 DOM。Wiki 文件主要是它自己的语法,但我允许在需要时使用 HTML 标签。如果我正在处理 DOM,您的建议非常有效。谢谢。:)
2021-04-05 21:11:21

您没有指定您的环境和 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 测试中使用它,大概是它随着时间的推移,将变得更加主流。

谢谢@freedomn-m .. IE 不支持一个非常新的功能几乎完全不足为奇:) 但是,是的,值得一提的是,它无法挽救任何试图“调试”为什么他们尝试使用它不起作用的人正如预期的那样。
2021-03-14 21:11:21
这在 Chrome (v67) 中效果很好,但在 IE11 和 IEdge(v42) 中完全破坏了正则表达式(也停止逐行工作)
2021-03-31 21:11:21

[.\n]不起作用,因为点输入[](通过正则表达式定义;不仅仅是 javascript)表示点字符。您可以使用(.|\n)(或(.|[\n\r])) 代替。

[\s\S]是最常见的 JavaScript 习惯用法,用于匹配包括换行在内的所有内容。与基于交替的方法(如(.|\n). (它的字面意思“的任何字符空白或是任何字符不是空格。)
2021-03-28 21:11:21
你是对的,但问题是关于.and \n,为什么[.\n]不起作用。正如问题中提到的,这[^]也是不错的方法。
2021-03-30 21:11:21

我已经测试了它(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 字符串中允许使用空字符(请参阅此答案)。
2021-03-28 21:11:21