JS HTML编译器:如何编写兼容单行多行的合并正则表达式?
解决单行/多行HTML内容匹配的正则方案
刚好碰到过类似的问题!你遇到的核心问题其实是JavaScript正则里.的默认行为——它不匹配换行符,而你后来写的正则又强制要求至少有一个换行,所以才会顾此失彼。下面给你两种完美适配两种场景的解决方案:
方案1:使用ES2018+的dotAll模式(推荐)
从ES2018开始,JavaScript正则支持s修饰符(dotAll模式),加上它之后,.就可以匹配包括换行符在内的所有Unicode字符了。这样你只需要在原来的(.*?)基础上加上s修饰符,就能同时处理单行和多行内容。
比如你要匹配标签内的内容,正则可以写成:
const regex = /<([a-z]+)>(.*?)<\/\1>/s;
测试例子:
- 单行HTML:
<p>Hello Stack Overflow</p>→ 匹配到内容Hello Stack Overflow - 多行HTML:
<p>Hello\nStack\nOverflow</p>→ 同样能完整匹配到带换行的内容
用match()调用的话:
const singleLineStr = "<p>Hello Stack Overflow</p>"; const multiLineStr = "<p>Hello\nStack\nOverflow</p>"; console.log(singleLineStr.match(regex)[2]); // 输出 "Hello Stack Overflow" console.log(multiLineStr.match(regex)[2]); // 输出 "Hello\nStack\nOverflow"
方案2:兼容旧版JavaScript的替代写法
如果你的运行环境不支持ES2018(比如一些老旧浏览器),可以用[\s\S]代替.——这个字符集包含了所有空白字符(包括换行)和非空白字符,本质上和dotAll模式的.效果完全一致。
对应的正则写法:
const regex = /<([a-z]+)>([\s\S]*?)<\/\1>/;
这个正则同样能同时匹配单行和多行的HTML内容,用法和上面一致。
为什么你原来的写法有问题?
(.*?):默认.不匹配\n,所以遇到换行就会停止匹配,导致多行内容被截断(.*?(\n))+.*?:这个正则强制要求至少有一个\n存在,所以单行内容(没有换行)根本匹配不上
内容的提问来源于stack exchange,提问作者Daniyal
相关产品推荐
相关产品推荐

