将HTML字符串中的所有空格与JavaScript匹配
假设您有如下HTML字符串:将HTML字符串中的所有空格与JavaScript匹配,javascript,html,regex,replace,Javascript,Html,Regex,Replace,假设您有如下HTML字符串: <div id="loco" class="hey" >lorem ipsum pendus <em>hey</em>moder <hr /></div> lorem ipsum pendus heymoder 并且需要在每个空格字符后面放置元素。。。。我正在做的是: HTMLtext.replace(/\s{1,}/g, ' <br/>'); 替换(/\s{1,}/g,“”); 然而
<div id="loco" class="hey" >lorem ipsum pendus <em>hey</em>moder <hr /></div>
lorem ipsum pendus heymoder
并且需要在每个空格字符后面放置
元素。。。。我正在做的是:
HTMLtext.replace(/\s{1,}/g, ' <br/>');
替换(/\s{1,}/g,“”);
然而,问题是,这也会在标记之间(标记属性之间)的空格字符后插入分隔符,我当然只想对标记文本内容这样做。不知怎么的,我对正则表达式总是很不熟悉——有人能帮我吗
因此,基本上要进行我最初的空白匹配,但前提是它不在<和>?正则表达式不是一个很好的工具。您应该使用DOM,而不是原始HTML字符串 对于一个快速而肮脏的解决方案,它假定字符串中除了分隔标记的字符外没有
字符,您可以尝试以下方法:
result = subject.replace(/\s+(?=[^<>]*<)/g, "$&<br/>");
result=subject.replace(/\s+(?=[^]*有关迭代dom和用
元素替换空白的信息,请参阅。修改后的代码为:
(function iterate_node(node) {
if (node.nodeType === 3) { // Node.TEXT_NODE
var text = node.data,
words = text.split(/\s/);
if (words.length > 1) {
node.data = words[0];
var next = node.nextSibling,
parent = node.parentNode;
for (var i=1; i<words.length; i++) {
var tnode = document.createTextNode(words[i]),
br = document.createElement("br");
parent.insertBefore(br, next);
parent.insertBefore(tnode, next);
}
}
} else if (node.nodeType === 1) { // Node.ELEMENT_NODE
for (var i=node.childNodes.length-1; i>=0; i--) {
iterate_node(node.childNodes[i]); // run recursive on DOM
}
}
})(content); // any dom node
(函数迭代节点(node){
如果(node.nodeType==3){//node.TEXT\u节点
var text=node.data,
words=text.split(/\s/);
如果(单词长度>1){
node.data=字[0];
var next=node.nextSibling,
parent=node.parentNode;
对于(变量i=1;i=0;i--){
迭代_节点(node.childNodes[i]);//在DOM上运行递归
}
}
})(内容);//任何dom节点
()好的,所以您不希望匹配HTML标记中的空格。只有正则表达式不足以满足此要求。我将使用a来完成此工作。您可以看到输出
var lexer=新lexer;
var结果=”;
addRule(//,函数(c){//标记的结尾
this.state=0;//返回状态0-初始状态
结果+=c;//复制到输出
},[2]);//仅当处于状态2时应用此规则
lexer.addRule(/。|\n/,函数(c){//匹配任何字符
结果+=c;//复制到输出
},[2]);//仅当处于状态2时应用此规则
lexer.addRule(/\s+/,函数(){//匹配一个或多个空格
结果+=“
”;//替换为“
”
});
lexer.addRule(/。|\n/,函数(c){//匹配任何字符
结果+=c;//复制到输出
})其他一切
lexer.input='lorem ipsum pendus heymoder
';
lexer.lex();
当然,lexer是一个非常强大的工具。您也可以跳过标记中属性值内的尖括号。但是我将留给您来实现。祝您好运。在一般情况下,使用正则表达式解析HTML是不可能的。只有当您知道HTML源以特定方式受到约束时,才能完成此操作。如果它真的可以是任意的HTML片段,那么你就不能用正则表达式来实现。将HTML交给浏览器,让它构建一个DOM片段,然后查找文本节点并修改它们。谢谢,是的,我知道这些问题,但我并不是真的解析HTML。只是尝试获取空白字符。我正在这样做在一个由我控制的HTML的有限环境中,我可以用DOM来实现它(我最初就是这么做的)-但我正试图避免这种情况,因为DOM操作成本很高,我正试图对代码进行一些优化。问题是,为了确定哪些空白字符需要替换,哪些不需要,你必须非常接近解析HTML。只是为了确保它不在<和>-不关心其他任何事情…但不要没有那么复杂的情况,我不认为是的,如果你确定属性值中没有尖括号,没有CDATA节等,那应该没问题。我想前面应该是[^]*(@Bergi:我想我们不想在最后一个标记后插入
,是吗?我不确定…谢谢@TimPietzcker-这似乎很好!我已经在DOM中使用了它,但这实际上是一种优化我的JS代码的尝试。该函数可以处理大量文本,因此直接修补DOM并不是最好的解决方案t我想。你能帮我解释一下吗?我假设它是匹配的空格,只要它不在<和>之间,对吗?@Tim:也许不在最后一个单词之后(假设有空格),但如果前面没有标记,则仍应替换任何空格。@Michael:我已编辑了我的答案。希望这能让答案更清楚。请务必考虑Bergi的建议-如果要匹配字符串中最后一个标记后的空格,则需要使用/\s+(?=[^]*(?:谢谢,但正如其他评论中提到的,这是一次优化尝试。我在DOM中已经有过这种尝试,但理论是DOM操作的成本比仅仅玩字符串要高很多。这也是有意义的。我在这里快速检查了一下,看它是否更快,是的-在大多数浏览器上,它的速度是原来的两倍…@Michael:谢谢你的帮助非常有趣的是,Safari操纵DOM的速度与正则表达式一样快(而且总体上是最快的),因此这不是正则表达式的内置优势。是的,我也对此感到惊讶——但我认为这是Safari 6(或支持jsperf的基准JS)中的一个bug.我刚刚用旧版Safari 5.1进行了测试,结果与其他浏览器相同。加上iPhone/iPad/Chrome上类似的WebKit引擎都是一样的…最后,修补DOM的速度与纯数学/字符串操作的速度是一样的,这也是毫无意义的…谢谢Aadit-这是一个非常有趣的库,但我并没有将外部代码放入其中,因为我正在尝试优化我的代码。另外,通过快速查看库源代码,您仍然在使用正则表达式,对吗?是的,我是。为什么要重新发明轮子?=)
(function iterate_node(node) {
if (node.nodeType === 3) { // Node.TEXT_NODE
var text = node.data,
words = text.split(/\s/);
if (words.length > 1) {
node.data = words[0];
var next = node.nextSibling,
parent = node.parentNode;
for (var i=1; i<words.length; i++) {
var tnode = document.createTextNode(words[i]),
br = document.createElement("br");
parent.insertBefore(br, next);
parent.insertBefore(tnode, next);
}
}
} else if (node.nodeType === 1) { // Node.ELEMENT_NODE
for (var i=node.childNodes.length-1; i>=0; i--) {
iterate_node(node.childNodes[i]); // run recursive on DOM
}
}
})(content); // any dom node
var lexer = new Lexer;
var result = "";
lexer.addRule(/</, function (c) { // start of a tag
this.state = 2; // go to state 2 - exclusive tag state
result += c; // copy to output
});
lexer.addRule(/>/, function (c) { // end of a tag
this.state = 0; // go back to state 0 - initial state
result += c; // copy to output
}, [2]); // only apply this rule when in state 2
lexer.addRule(/.|\n/, function (c) { // match any character
result += c; // copy to output
}, [2]); // only apply this rule when in state 2
lexer.addRule(/\s+/, function () { // match one or more spaces
result += "<br/>"; // replace with "<br/>"
});
lexer.addRule(/.|\n/, function (c) { // match any character
result += c; // copy to output
}); // everything else
lexer.input = '<div id="loco" class="hey" >lorem ipsum pendus <em>hey</em>moder <hr /></div>';
lexer.lex();