在String中包装字符,不包括使用Javascript Regex的Link标记

时间:2013-12-19 18:39:01

标签: javascript regex

修改

继承人我要做的事情......

想象一下,如果我的文本里面有一些html标签(它仍然是一个字符串):

var string = '<p>Hello, my name is Mauricio</p><p>Hi, my name is Patricia</p><p class="warn">Yeah, My name is Carl</p><a href="#"><img src="#" /></a>';

我想用

包装所有字母“a”
 <span class="ui-match"></span>

但我不能替换标签中的任何内容,也不能替换内部的内容,也不能替换

元素中的类。

因此,如果我想从该字符串中包装所有字母“a”,它将返回如下:

<p>Hello, my n<span class="ui-match">a</span>me is M<span class="ui-match">a</span>uricio</p><p>Hi, my n<span class="ui-match">a</span>me is P<span class="ui-match">a</span>trici<span class="ui-match">a</span></p><p class="warn">Ye<span class="ui-match">a</span>h, My n<span class="ui-match">a</span>me is C<span class="ui-match">a</span>rl</p><a href="#"><img src="#" /></a>

包裹的所有字母“a”
 <span class="ui-match"></span>

,但链接和段落不是。

这个字符串也来自API,所以它的动态...我正在搜索的这封信是动态的,所以它可以是“a”或“abc”......它一定不能区分大小写

感谢

3 个答案:

答案 0 :(得分:1)

如果不使用正则表达式,使用DOM节点会更快:

var div = document.createElement('div'),
    children;

div.innerHTML = 'Hello, my name is mauricio, and i like <a href="#">Star Wars</a>';
children = div.childNodes;

for (var i = 0, len = children.length; i < len; i++) {
    console.log(children[i]);
    if (children[i].nodeType === 3) {
        children[i].nodeValue = children[i].nodeValue.replace(/a/g, 'R');
    }
}

console.log(div.innerHTML);

N.B。:我在这里使用innerHTML属性作为示例方式,但是由于性能相当低,不建议使用它。

DEMO: http://jsfiddle.net/N7rdW/


UPDATE:

根据您的更新,您应该更好地使用我的答案中的方法来解决HERE中的另一个问题。代码有点复杂,但速度相当快(不记得innerHTML用法):

var div = document.createElement('div');
div.innerHTML = 'Hello, my name is mauricio, and i like <a href="#">Star Wars</a>';

for (var i = 0, children = div.childNodes, len = children.length; i < len; i++) {
    var child = children[i];
    if (child.nodeType === 3 && child.nodeValue.indexOf('a') > -1) {
        var segments = child.nodeValue.split('a');
        for (var k = 0, lk = segments.length; k < lk; k++) {
            div.insertBefore(document.createTextNode(segments[k]), child);
            if (k < lk - 1) {
                var span = document.createElement('span');
                span.className = 'ui-match';
                span.appendChild(document.createTextNode('R'));
                div.insertBefore(span, child);
            }
        }
        div.removeChild(child);
    }
}

console.log(div.innerHTML);

DEMO: http://jsfiddle.net/T4ZXA/6/

答案 1 :(得分:1)

我建议你将问题分成两个较小的问题:

  1. 抓取所有标签的文字内容。
  2. 使用<span class="ui-match"></span>
  3. 包装字符

    使用RegExp to parse HTML is a bad idea但在这种情况下,因为您似乎控制输入结构,您可以使用它来简化逻辑。

    使用单一的RegExp会非常困难,因此最好做2 String#replace而不是1。function replaceHtmlContent(str, match, replaceFn) { // we use the "g" and "i" flags to make it replace all occurrences and ignore case var re = new RegExp(match, 'gi'); // this RegExp will match any char sequence that doesn't contain "<" or ">" // and that is followed by a tag return str.replace(/([^<>]+)(?=<[^>]+>)/g, function(s, content){ return content.replace(re, replaceFn); }); } 。通用实现如下:

    function wrapMatch(src, match) {
      return replaceHtmlContent(src, match, function(str){
        return '<span class="ui-match">'+ str +'</span>';
      });
    }
    

    可以抽象为:

    var output = wrapMatch(input, 'a');
    

    以后用作:

    {{1}}

    将给出示例输入的预期结果。

    DEMO: http://jsbin.com/ovUFEsas/4/edit

答案 2 :(得分:1)

此解决方案是否符合您的要求?

string = string.replace(/a(?![^<]*?>)/g, '<span class="ui-match">a</span>');

关于(?![^<]*?>)的一点帮助(粗略地说:“有些文字没有跟>”):

(?!...)   not followed by
[^<]*     any char except "<", zero or more times
?>        until next ">"

包含在函数内:

function replace(html, text, replacement) {
    // RegExp.escape : http://stackoverflow.com/q/3561493/1636522
    var re = new RegExp('(' + RegExp.escape(text) + ')(?![^<]*?>)', 'g');
    return html.replace(re, replacement);
}
var html = '<a class="azerty"> azerty &lt; azerty </a>';
html = replace(html, 'azerty', '<b>$1</b>');
// "<a class="azerty"> <b>azerty</b> &lt; <b>azerty</b> </a>"