javascript中字符串上的多个正则表达式替换冲突
multiple conflicting regex replacements on string in javascript
我正在使用regex制作一个简单的模式匹配器,它可以接受我的regex模式,并以我想要的格式生成一个新字符串。当我注意到我有相邻的regex模式相互冲突,并且无法再正确执行操作时,起初看似简单的程序变得非常复杂,因为新形成的字符串包含的字符会与我刚刚替换的内容冲突。。。(我知道这可能有点令人困惑,所以我将提供一个例子)。
var str = "I am the greatest";
var r1 = /(am)/g;
var r2 = /(i)/ig;
var newstr = str.replace(r1,"<i>$1</i>").replace(r2,"<h1>$1</h2>");
console.log(newstr);
//returns "<h1>I</h2> <<h1>i</h2>>am</<h1>i</h2>> the greatest"
我知道这是一个天真的例子,但它完美地说明了我的观点。我希望发生的是,第二个(以及所有正在进行的)替换对原始字符串执行匹配,但对变异字符串执行替换,以便上例中的newstr
var读取"<h1>I</h2> <i>am</i> the greatest"
。我已经考虑过使用sourcemaps来引用regexs的映射,并执行一个自定义替换函数,该函数引用映射来在正确的位置执行替换。。。。但我似乎无法掌握足够的源地图来实现这一点。。。。任何帮助都将不胜感激。
您可以想出一个在字符串中永远找不到的字符序列,使用该序列临时包装所有replace
项的结果,然后在所有replace
项完成后剥离该序列。
例如,选择#{...}
的序列,您需要将其添加到所有正则表达式模式中。类似于:
var seq = /#'{(.*?)'}/g; // our sequence -- #{...}
// Prepend (#'{(.*?)'})| to the given regex
var newExpression = function(regex) {
var splitRegex = regex.toString().split('/'),
flags = splitRegex.pop();
splitRegex.shift(); // get rid of the first blank entry from the opening '/' in the regex
return new RegExp('(' + seq.toString().slice(1, -2) + ')|' + splitRegex.join('/'), flags);
};
var r1 = newExpression(/(am)/g); // returns /(#'{(.*?)'})|(am)/g
var r2 = newExpression(/(i)/ig); // returns /(#'{(.*?)'})|(i)/ig
如果您不想手动将(#'{.*?'})|
添加到所有模式的开头,可以这样做。我们这样做是为了在随后的通行证中识别这个序列,而不是触摸它
接下来,确保在所有比赛的开始处粘贴#{
,在比赛结束时粘贴}
;
str.replace(r1, '#{<i>$1</i>}')...
将实现这一目标。不幸的是,这对我们来说还不够智能——我们需要单独保留与序列(#{...}
)匹配的项目;换句话说,用它们自己来代替它们。这里有一个功能可以很好地为我们做到这一点:
var replaceFunc = function(match) {
return match.match(seq)
? match
: '#{<' + this.tag + '>' + match + '</' + this.tag + '>}';
};
然后像这样使用:
var newStr = str.replace(r1, replaceFunc.bind({tag: 'i'}))
.replace(r2, replaceFunc.bind({tag: 'h1'}))
.replace(seq, '$1'); // strip the sequence, leaving the desired string
当然,我知道在实际实现中不一定要使用HTML标记,而且这个序列可能还不够。但是,您现在应该能够轻松地修改seq
、replaceFunc
和/或绑定replaceFunc
的对象,以满足您的需要。
这是一个JSFiddle。祝你好运!
正如我在你的第一次替换中看到的,你将am替换为am,所以在第二次替换所有I时,这意味着你不仅替换了"I"和<"i">,所以你得到了你写的结果。这是regexp,它不能取代标签"i":
r2 = /(i)[^>]/ig
- 如何用正则表达式替换特定的JavaScript注释
- 用特定的javascript正则表达式替换每个单词
- 如何用JavaScript正则表达式替换href中的所有内容
- 使用 JavaScript 中的正则表达式替换大文本中两个字符之间的每个出现的字符串
- Javascript 正则表达式替换为转义的反斜杠
- 使用 JavaScript 正则表达式替换文本中的类似字符串
- 在特殊标记之外使用 JavaScript 正则表达式替换
- 如何使用 javascript 在正则表达式替换中表示大括号
- 在字符串 JavaScript 中使用正则表达式替换
- 用Javascript正则表达式替换iframe到可点击的YouTube链接
- JS正则表达式替换编号
- 正则表达式:替换javascript中的字符串
- Javascript正则表达式替换以转换文本
- 正则表达式替换为插入符号
- 在javascript中用正则表达式替换空格
- 用正则表达式替换javascript
- 使用 JavaScript 正则表达式替换和递增整数值
- JS 正则表达式:替换字符串中的所有数字
- 正则表达式替换
- JS - 正则表达式替换在一次调用中发生多次,如何让它运行一次