如何在多行上使用 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]
?
让我快速指出您对贪婪运算符的测试是被操纵的。 /<p>Can[^]*?<\/p>/
与 /<p>Can[^]*<\/p>/
的内容不匹配。贪婪的变种应该改成/<p>(?:[^<]|<(?!\/p>))*<\/p>/
来匹配相同的内容。【参考方案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 正则表达式?的主要内容,如果未能解决你的问题,请参考以下文章