移除字符串过多空行:为何第二种正则方法对含空白行无效?
为什么第二种正则方法对含空白字符的行无效?
这个问题的核心坑点在于正则构造函数的字符串转义规则,咱们一步步拆解清楚:
先看第一个方法为什么有效
你写的第一个正则用的是正则字面量,逻辑是完全通顺的:
string.replace(/^(\s*\n){2,}/gm, '\n');
gm模式让^匹配每一行的行首,\s*能匹配任意数量的空白字符(空格、制表符、换行前的空白都算);(\s*\n)代表“一行空白内容+换行”的组合,{2,}匹配连续2次及以上的这种组合,最后替换成单个换行,自然能把连续的空行(哪怕行内带空白)合并。
第二个方法失效的关键原因
当你用new RegExp()构造正则时,传入的参数是字符串字面量,而字符串里的反斜杠\会被先解析一次——也就是说,你写的\s在字符串里会被直接当成字母s,而不是正则里代表空白的元字符\s!
举个直观的例子:
你原本想构造的正则是^(\s*\n){2,},但如果写成字符串'^(\s*\n){2,}',实际被解析成的正则会变成^(s* ){2,}(\s被解析成s,\n被解析成实际换行),这完全不是你想要的匹配规则,当然抓不到目标内容。
另外还有个小细节:如果EOL是\r\n,直接把它放到正则字符串里会被当成实际的换行符,而不是正则元字符\r\n,也需要提前转义处理。
修正后的第二个方法
把所有需要转义的地方做双重转义,同时处理EOL的转义:
var string = ` foo bar .................... ....................... ........... baz `; // 先确定换行符类型 var EOL = string.match(/\r\n/gm) ? '\r\n' : '\n'; // 把EOL转义成正则能识别的字符串形式 var escapedEOL = EOL === '\r\n' ? '\\r\\n' : '\\n'; // 构造正则时,\s要写成\\s(双重转义),确保正则能识别空白元字符 var regExp = new RegExp(`^(\\s*${escapedEOL}){2,}`, 'gm'); // 执行替换 string = string.replace(regExp, EOL); console.log(string);
修正后,第二个方法就能和第一个方法一样正常工作了——本质要记住:用RegExp构造函数时,所有正则里的反斜杠都要写成\\,因为字符串会先“吃掉”一层转义。
内容的提问来源于stack exchange,提问作者john c. j.
相关产品推荐
相关产品推荐

