2010-08-27 44 views
1

我試圖替換一個單詞的所有實例,在某些HTML標記之間說「foo」。JavaScript正則表達式匹配和替換匹配內的多個事件

<span id=foo> blah blah foo blah foo blah </span> 

我想更換不符合欄中的標籤FOO的所有實例,所以最終的結果是:

<span id=foo> blah blah bar blah bar blah </span> 

注意的是,在span標記爲「foo」並沒有被替換。

我可以設法將「foo」的第一次(或最後一次)發生替換爲我的正則表達式,但不是多個實例。這是我應該放棄而不是試圖用正則表達式解析這種情況嗎?

這裏是正則表達式排序的作品:

RegExp('(>[\\w\\s]*)\\bfoo\\b([\\w\\s]*<)',"ig" 

或沒有JavaScript語法:

s/>([\w\s]*)\bfoo\b([\w\s]*<)/ 

這個語法允許我來匹配(或應該)比賽之類的東西

[foo]但不是bar-foo或barfoobar ...將被替換的foo的任何發生都需要站在它自己的位置上,它不能共存換句話說,

作爲一個說明,「等等」是不同的長度,可以是許多不同的單詞,沒有單詞,或這些的任何組合。

感謝您的任何建議。

回答

0

我試圖做到這一點在錯誤的道路。這是我創建的解決方案,似乎很好。它使用兩個遞歸函數+ DOM遍歷+正則表達式來創建適當的文本和跨度節點。

function replaceText(element, pattern, syn_text) { 

for (var childi = 0; childi < element.childNodes.length;childi++) { 
    var child= element2.childNodes[childi]; 
    if (child.nodeType==1 && child.className!=syn_text){ //make sure we don't call function on newly created node 
     replaceText(child, pattern, syn_text); //call function on child 
    } 
    else if (child.nodeType==3){ //this is a text node, being processing with our regular expression 
     var str = child.data; 
     str = str.replace(pattern,function(s, p1,p2,p3) { 
      var parentNode = child.parentNode; 
      do_replace(s, p1,p2,p3,parentNode,pattern,syn_text); 
      parentNode.removeChild(child); //delete old child from parent node. we've replaced it with new nodes at this point 
     }); 
    } 
}} 




function do_replace(s, p1,p2,p3,parentNode,pattern,syn_text) { 
    if(p1.length>0){ //this might not be necessary 
    //create textnode 
     var text_node = document.createTextNode(p1); 
     parentNode.appendChild(text_node); 
    } 
    if(p2.length > 0){ //create a span + next_node for the highlighting code 
     spanTag = document.createElement("span"); 
     spanTag.id = "SString" + id++; 
     spanTag.className = syn_text; 
     spanTag.innerHTML = p2; 
     parentNode.appendChild(spanTag); 
    } 
    if(p3.length > 0){ 
     //test to see if p3 contains another instance of our string. 

     if(pattern.test(p3)){ //if there is a instance of our text string in the third part of the string, call function again 
      p3.replace(pattern,function(s, p1,p2,p3) { 
      //debugger; 
      do_replace(s, p1,p2,p3,parentNode,pattern); 
      return; 
      }); 
     } 
     else{ //otherwise, it's just a plain textnode, so just reinsert it. 
      var text_nodep3 = document.createTextNode(p3); 
      parentNode.appendChild(text_nodep3); 
      return; 
     } 
    } 
    else{ //does this do anything? 
     return; 
    } 
return} 

調用此函數如下:

syn_highlight = "highlight_me"; //class to signify highlighting 
pattern = new RegExp('([\\w\\W]*?)\\b('+ searchTerm + '[\\w]*)\\b([\\w\\W]*)',"ig"); 
replaceText($('#BodyContent')[0],pattern,syn_highlight); 
0

以下似乎工作:

var str = "foo yea foot bfoo <span id=foo> blah blah foo blah foo blah </span> foo again <span id=foo>foo again</span>\n\nthis is foo again"; 
var r = new RegExp("\\bfoo\\b","ig"); 
str = str.replace(r, "'it works'"); 
alert(str); 
+0

感謝您的答覆。這個問題是表達式(這是我*使用的,btw)是它替換了span標籤內的「foo」。我試圖通過創建一個正則表達式來避免這種情況* *不匹配標籤中的項目。 – user210099 2010-08-27 14:42:08

+0

好的,但它不匹配id = foo,它只是單獨匹配foos。 – Zafer 2010-08-28 10:40:34

1

如果你從正則表達式的結果保存爲匹配對象是這樣的:

var regex = new RegExp('(>[\\w\\s]*)\\bfoo\\b([\\w\\s]*<)',"ig"); 
var mystring = "<span id=foo> blah blah foo blah foo blah </span>"; 
var match = regex.exec(mystring); 

您可以使用另一種更簡單的正則表達式來再看看在匹配的字符串處查找多個「foo」。匹配的字符串將在match[0]

0
str = str.replace(/(>[^<]*<)/g, function(s, p1) { 
    return p1.replace(/\bfoo\b/g, ''); 
}); 
3

我不知道如果任何人前面提到這一點,但:

不要使用正則表達式來操作HTML。

這是一個糟糕的工具,遠遠不夠處理HTML的複雜性。如果你開始在標記內部替換字符串,你可以輕鬆地給自己打破標記,但也可能導致HTML注入漏洞,可能導致跨站點腳本漏洞。這:

(>[\\w\\s]*) 

不足以,以確保正在更改HTML不標記。在屬性值中有一個>字符是完全有效的,更不用說所有其他標記結構。

如果您的語言是在Web瀏覽器中運行的JavaScript,那麼甚至不需要嘗試,因爲瀏覽器已經很好地將您的文檔解析爲Element對象和Text節點。不要要求瀏覽器將所有這些文檔對象重新序列化爲新的HTML,然後破解HTML並將其寫回innerHTML!除了緩慢之外,這將破壞所有現有內容以用新對象替換它,這具有失去所有不可串行信息(例如表單字段值,JavaScript引用,擴展和事件處理程序)的副作用。

您可以簡單地遍歷元素中您想要進行替換的所有Text節點。簡單的例子:

function replaceText(element, pattern, replacement) { 
    for (var childi= element.childNodes.length; childi-->0;) { 
     var child= element.childNodes[childi]; 
     if (child.nodeType==1) # Node.ELEMENT_NODE 
      replaceText(child, pattern, replacement); 
     else if (child.nodeType==3) # Node.TEXT_NODE 
      child.data= child.data.replace(pattern, replacement); 
    } 
} 

replaceText($('#foo')[0], /\bfoo\b/gi, 'bar'); 
+0

總體而言,你所說的是真實的,但如果問題有充分的界限(例如,處理一個簡單的跨度序列),那麼正則表達式對於做這種事情是可以的 – 2010-08-27 01:38:17

+0

謝謝,這是一個很好的起點,我的最後解!我會接受這個作爲我的答案,但我的解決方案實際上適用於我在上面定義的目的。 – user210099 2010-08-30 18:23:27

0

我很困惑,爲什麼你不能做的:

var replacement = $('#foo').html().replace(/\bfoo\b/g, ''); 
$('#foo').html(replacement); 
1

您好我在做一個reg前用jQuery代替大膽所有p標籤的所有第一句話就我自己的網站。 我認爲該代碼也可能會回答您的查詢。


<!DOCTYPE html> 
<html> 
<head> 
<title>JQ Replace foo</title> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<style type="text/css"> 
#foo {color:#00c;} 
</style> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> 
<script type="text/javascript"> 
$(document).ready(function(){ 
$('* #foo').each(function(){ //use star to select all elements with id=foo 
var me = $(this); 
me.html(me.text().replace(/foo/g,"bar")); // only change text 'foo' to 'bar' , not the html id=foo 
}); 
}); 
</script> 
</head> 
<body> 
<div id="foo"> blah blah foo blah foo blah </div> 
<p id="foo"> blah blah foo blah foo blah </p> 
<a id="foo"> blah blah foo blah foo blah </a> 
</body> 
</html> 

簡單,但對我的作品 約翰·吉斯(NZ)