我正在尝试替换字符串中给定单词的所有出现,但该单词可能包含需要转义的特殊字符。这是一个例子:
ERA是每九个投手放弃的跑步的平均值 投球局。同时,ERA +,经过调整的ERA,是一名投手 根据投手的棒球场获得跑动平均值(ERA)(以防万一) 球场有利于投手或投手)和投手的ERA 联赛。
我希望能够做到以下几点:
string = "The ERA..." // from above
string = string.replaceAll("ERA", "<b>ERA</b>");
string = string.replaceAll("ERA+", "<u>ERA+</u>");
没有ERA和ERA冲突。我一直在使用protoype replaceAll posted previously以及在SO上的其他地方找到的正则表达式(我似乎无法在历史记录中找到链接)
String.prototype.replaceAll = function (find, replace) {
var str = this;
return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace);
};
function loadfunc() {
var markup = document.getElementById('thetext').innerHTML;
var terms = Object.keys(acronyms);
for (i=0; i<terms.length; i++) {
markup = markup.replaceAll(terms[i], '<abbr title=\"' + acronyms[terms[i]] + '\">' + terms[i] + '</abbr>');
}
document.getElementById('thetext').innerHTML = markup;
}
基本上代码的作用是在缩放时添加标记以包含鼠标悬停时的定义。问题是当前的正则表达式太松散了。我以前的尝试部分工作,但未能在ERA和ERA +之类的东西之间产生差异,或者完全跳过“K / 9”或“IP / GS”之类的东西(这应该是匹配的,而不是“IP”或“GS”单独)
我应该提一下,首字母缩略词是一个看起来像的数组:
var acronyms = {
"ERA": "Earned Run Average: ...",
"ERA+": "Earned Run Average adjusted to ..."
};
另外(尽管这很明显)'thetext'
是一个包含一些文本的虚拟div。 loadfunc()
函数从<body onload="loadfunc()">
谢谢!
答案 0 :(得分:1)
好的,在查看你的jsFiddle后,这可以解决很多问题。
我认为您将获得的最佳效果是搜索以大写字母开头的整个单词,其中可能包含/
或%
。这样的事情:([A-Z][\w/%]+)
警告:无论你如何做到这一点,如果你在浏览器中这样做(例如你无法更新原始数据),那将是一个过程密集型。
你可以像这样实现它:
var repl = str.replace(/([A-Z][\w\/%]+)/g, function(match) {
//alert(match);
if (match in acronyms)
return "<abbr title='" + acronyms[match] + "'>" + match + "</abbr>";
else
return match;
});
这是一个有效的jsFiddle:http://jsfiddle.net/remus/9z6fg/
请注意,jQuery不是必需的,只是在这种情况下使用jQuery以便于更新jsFiddle中的DOM。
答案 1 :(得分:0)
您希望使用具有负前瞻的正则表达式:
string.replace(/\bERA(?!\+)\b/g, "<b>ERA</b>");
和
string.replace(/\bERA\+/g, "<u>ERA+</u>");
为了更好的衡量,添加了零宽度字边界\b
,因此您不会意外地匹配“BERA”等字符串。
另一个想法是将最长的密钥列表排序为最小的密钥。这样你肯定会在'ERA'之前替换所有'ERA +',所以没有子串冲突。