2010-08-11 61 views
4

我正在使用JavaScript來完成一些正則表達式。考慮到我正在處理格式良好的源代碼,並且我希望在[,。]之前移除任何空格,並且在[,。]之後只保留一個空格,但[,。]是數字的一部分。因此,我使用:正則表達式來搜索/替換文本,而不是HTML屬性

text = text.replace(/ *(,|\.) *([^ 0-9])/g, '$1 $2'); 

問題是,這也取代了html標記屬性中的文本。例如我的文本(總是用標籤包裝):

<p>Test,and test . Again <img src="xyz.jpg"> ...</p> 

現在添加一個空格,這樣src="xyz. jpg"預期不會。我怎樣才能重寫我的正則表達式?我想要的是

<p>Test, and test. Again <img src="xyz.jpg"> ...</p> 

謝謝!

+8

這不是正則表達式所擅長的,因爲HTML不是常規語言。有太多的範圍/嵌套/上下文。 – CaffGeek 2010-08-11 15:26:25

+1

是否通過DOM訪問該文本? – Gumbo 2010-08-11 15:39:06

+0

是的,我想,即使我沒有嘗試過。我想把它寫成一個CKEditor插件,這就是爲什麼我說「格式良好」(好吧,我的意思是XHTML無論如何)。我有源代碼,但我認爲我可以得到的是DOM元素。 – jcisio 2010-08-13 08:10:12

回答

4

您可以使用超前來確保匹配不在標記內發生:

text = text.replace(/(?![^<>]*>) *([.,]) *([^ \d])/g, '$1 $2'); 

通常的警告適用於屬性值中的CDATA節,SGML註釋,SCRIPT元素和尖括號。但是我懷疑你的真正問題會出現在「簡單」文本的變幻莫測之中; HTML甚至不在同一聯盟中。 :D

+0

我不工作。 「測試和」應該成爲「測試和」。我也很想看看,但我無法得到它。就像尋找「...>除了<(尋找/替換的文本)之外的東西」。 而且我認爲上面的[^ <>] *部分是沒有必要的。 – jcisio 2010-08-13 08:21:25

+0

當我測試它時,那裏有更多的星號,但它們消失了。現在就試試。 – 2010-08-14 04:00:30

+0

我正在使用另一種解決方案。但是這個更好:)謝謝。 – jcisio 2011-02-01 14:04:50

0

Html不是「常規語言」,因此正則表達式不是解析它的最佳工具。你可能更適合使用html parser like this one to get at the attribute,然後應用正則表達式來處理值。

享受!

+0

這是一個Java的HTML解析器。他想用JavaScript來做到這一點。 – BalusC 2010-08-11 16:37:40

0

Don't parse regexHTML with HTMLregex。如果您知道您的HTML格式正確,請使用HTML/XML解析器。否則,先通過Tidy運行它,然後使用XML解析器。

+2

你可能的意思是「不要用正則表達式解析HTML」,而不是相反。 ;) – scy 2010-08-11 15:31:29

+3

@Scytale - 他只是徹底的;只要我們談論這個問題,人們不應該用HTML解析RegEx! ;) – 2010-08-11 15:34:30

+0

@Scytale @Richard haha​​ha我甚至沒有看到。我的壞 - 將修復:) – 2010-08-11 16:07:32

1

不要試圖重寫你的表達來做到這一點。你不會成功,幾乎肯定會忘記一些角落案例。在最好的情況下,這會導致令人討厭的錯誤,在最壞的情況下,你會引入安全問題。相反,如果您已經在使用JavaScript並且具有格式正確的代碼,請使用真正的XML解析器遍歷文本節點,並僅將正則表達式應用於它們。

0

如上所述,以前很多次,HTML不是正規語言,因此不能用正則表達式進行分析。

您將不得不遞歸執行此操作;我建議爬行DOM對象。

嘗試這樣的事情......

function regexReplaceInnerText(curr_element) { 
    if (curr_element.childNodes.length <= 0) { // termination case: 
               // no children; this is a "leaf node" 
     if (curr_element.nodeName == "#text" || curr_element.nodeType == 3) { // node is text; not an empty tag like <br /> 
      if (curr_element.data.replace(/^\s*|\s*$/g, '') != "") { // node isn't just white space 
                    // (you can skip this check if you want) 
       var text = curr_element.data; 
       text = text.replace(/ *(,|\.) *([^ 0-9])/g, '$1 $2'); 
       curr_element.data = text; 
      } 
     } 
    } else { 
     // recursive case: 
     // this isn't a leaf node, so we iterate over all children and recurse 
     for (var i = 0; curr_element.childNodes[i]; i++) { 
      regexReplaceInnerText(curr_element.childNodes[i]); 
     } 
    } 
} 
// then get the element whose children's text nodes you want to be regex'd 
regexReplaceInnerText(document.getElementsByTagName("body")[0]); 
// or if you don't want to do the whole document... 
regexReplaceInnerText(document.getElementById("ElementToRegEx")); 
1

如果可以通過DOM訪問文本,你可以這樣做:

function fixPunctuation(elem) { 
    // check if parameter is a an ELEMENT_NODE 
    if (!(elem instanceof Node) || elem.nodeType !== Node.ELEMENT_NODE) return; 
    var children = elem.childNodes, node; 
    // iterate the child nodes of the element node 
    for (var i=0; children[i]; ++i) { 
     node = children[i]; 
     // check the child’s node type 
     switch (node.nodeType) { 
     case Node.ELEMENT_NODE: 
      // call fixPunctuation if it’s also an ELEMENT_NODE 
      fixPunctuation(node); 
      break; 
     case Node.TEXT_NODE: 
      // fix punctuation if it’s a TEXT_NODE 
      node.nodeValue = node.nodeValue.replace(/ *(,|\.) *([^ 0-9])/g, '$1 $2'); 
      break; 
     } 
    } 
} 

現在只是通過DOM節點這樣的功能此:

fixPunctuation(document.body); 
fixPunctuation(document.getElementById("foobar")); 
+0

你拼錯函數名'fixPunctuation'作爲'fixPunctutation'幾次;) – 2010-08-11 16:05:58

+0

@Richard JP Le Guen:啊,你說得對,謝謝。修正了。 – Gumbo 2010-08-11 16:31:19