如何匹配HTML标签中未包含的所有引号?

时间:2014-12-15 22:24:37

标签: javascript html regex

在以下字符串中......

var str = 'Foobar is so "awesome."  I <span prop="nifty">"really"</span> <span prop="attr">think it is so</span> <span prop="nifty" prop="attr">"cool!"</span>'

...如何编写一个与引号(“)相匹配的正则表达式,包括awesome,really和cool,而不匹配HTML标记中的引号?

我正在使用JavaScript的替换函数将引号替换为&#34;

我希望有一个正则表达式,我可以使用......

str.replace(/regex-magic/g, "&#34;")

..给我输出......

Foobar is so `&#34;`awesome.`&#34;`  I <span prop="nifty">`&#34;`really`&#34;`</span> <span prop="attr">think it is so</span> <span prop="nifty" prop="attr">`&#34;`cool!`&#34;`</span>

非常感谢!!

4 个答案:

答案 0 :(得分:5)

与往常一样,使用正则表达式进行HTML / XML处理是一个非常糟糕的主意。

无论如何,我想可以使用以下正则表达式:

([^<]*<[^>]*>[^<]*)*?\"(.*?)\"

第一组用于确保每个打开的标签也被关闭。第二组确保您匹配引号之间的任何内容。


但是,如果您希望正确执行此操作,则可以使用tidy将其转换为xml文件,然后使用xmlint来执行 XPath 查询。我确定Javascript也有这样的工具。

示例(在bash中):

$ echo 'Foobar is so "awesome."  I <span prop="nifty">"really"</span> <span prop="attr">think it is so</span> <span prop="nifty" prop="attr">"cool!"</span>' | tidy -asxhtml -numeric 2>/dev/null | xmllint --html --xpath 'normalize-space(/)' - | grep -P -o '".*?"'
"awesome."
"really"
"cool!"

答案 1 :(得分:2)

我要做的是使用DOM解析器读取整个文档,然后将整个文档输出为有效的HTML。那么你甚至不必弄乱它,并且你将对你的无效模糊HTML得到最好的解释。

答案 2 :(得分:1)

str = str.replace(/"(?![^<>]*>)/g, "&#34;");

(?![^<>]*>)是一个负向前瞻(ref)。它从当前位置向前扫描(在这种情况下,在匹配报价后),查找关闭角括号(>)。如果它找到一个没有首先看到一个左括号(<),它必须在HTML标记内,所以匹配失败。

&#13;
&#13;
var str = 'Foobar is so "awesome."  I <span prop="nifty">"really"</span> <span prop="attr">think it is so</span> <span prop="nifty" prop="attr">"cool!"</span>';
str = str.replace(/"(?![^<>]*>)/g, "&#34;");
alert(str);
&#13;
&#13;
&#13;

正如其他响应者所说,最好尽可能将HTML 作为 HTML处理(通常是可能的)。像这样逐个字符地处理它,即使你是使用你正在使用的任何工具的专家,也很容易引入错误。

答案 3 :(得分:0)

对于这样的问题,我发现处理单个文本节点更容易,而不是通过正则表达式语法。

假设您的字符串在DOM元素中,您可以轻松创建一个元素,而不是将其附加到DOM。

我的函数在下面遍历子节点。如果孩子是文本节点,则会将"更改为&#34;。否则,它会与孩子一起递归调用。然后输出存储在textarea

function replaceQuotes(d) {
  var cn= d.childNodes;
  for(var i = 0 ; i < cn.length ; i++) {
    if(cn[i].nodeValue) {
      cn[i].nodeValue= cn[i].nodeValue.replace(/"/g,'&#34;');
    }
    else {
      replaceQuotes(cn[i]);
    }
  }
}

var str = 'Foobar is so "awesome."  I <span prop="nifty">"really"</span> <span prop="attr">think it is so</span> <span prop="nifty" prop="attr">"cool!"</span>'

var d= document.createElement('div');
d.innerHTML= str;
replaceQuotes(d);

document.querySelector('textarea').innerHTML= d.innerHTML;
textarea {
  width: 80%;
  height: 100px;
}
<textarea></textarea>