我正在使用JavaScript来做一些正则表达式。考虑到我正在使用格式良好的源,我想在[,。]之前删除任何空格,并且在[,。]之后只保留一个空格,除了[,。]是数字的一部分。因此我使用:
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>
谢谢!
答案 0 :(得分:4)
您可以使用前瞻来确保标记内没有匹配:
text = text.replace(/(?![^<>]*>) *([.,]) *([^ \d])/g, '$1 $2');
通常的警告适用于CDATA部分,SGML注释,SCRIPT元素和属性值中的尖括号。但我怀疑你的真正问题会出现在“普通”文本的变幻莫测之中; HTML甚至不在同一个联盟中。 :d
答案 1 :(得分:1)
不要尝试重写表达式来执行此操作。你不会成功,几乎肯定会忘记一些角落案件。在最好的情况下,这将导致令人讨厌的错误,在最坏的情况下,您将引入安全问题。
相反,当您已经使用JavaScript并且具有格式良好的代码时,请使用真正的XML解析器循环文本节点,并仅将正则表达式应用于它们。
答案 2 :(得分: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"));
答案 3 :(得分:0)
Html不是“常规语言”,因此正则表达式不是解析它的最佳工具。您可能更适合使用html parser like this one to get at the attribute,然后应用正则表达式来对值进行操作。
享受!
答案 4 :(得分:0)
Don't parse regexHTML with HTMLregex。如果您知道HTML格式正确,请使用HTML / XML解析器。否则,首先通过Tidy运行它,然后使用XML解析器。
答案 5 :(得分: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"));