簡體   English   中英

將字符換成字符串,不包括帶有Javascript正則表達式的Link標記

[英]Wrap character in String, excluding a Link tag with 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” ...它不能區分大小寫

謝謝

對於不使用正則表達式的情況,使用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);

注意:這里我以innerHTML屬性為例,但是由於性能較低,不建議利用它。

演示: http : //jsfiddle.net/N7rdW/


更新:

根據您的更新,您最好將我的答案中的方法用於此處的另一個問題。 代碼有點復雜,但是相當快(不要記住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);

演示: http : //jsfiddle.net/T4ZXA/6/

我建議您將問題分為2個較小的問題:

  1. 抓取所有標簽的文本內容。
  2. <span class="ui-match"></span>包裝字符

使用RegExp解析HTML是一個主意,但是在這種情況下,由於您似乎可以控制輸入結構,因此可以使用它來簡化邏輯。

使用單個RegExp確實很困難,因此最好使用2個String#replace而不是一個。 通用實現如下:

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');

這將為示例輸入提供預期的結果。

演示: http : //jsbin.com/ovUFEsas/4/edit

該解決方案符合您的要求嗎?

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>"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM