outerHTML.search(/\> *\</) ;// 在 outerHTML 上的正则表达式搜索有时会产生“错误”索引

Posted

技术标签:

【中文标题】outerHTML.search(/\\> *\\</) ;// 在 outerHTML 上的正则表达式搜索有时会产生“错误”索引【英文标题】:outerHTML.search(/\> *\</) ;// regex search on outerHTML yields 'wrong' index sometimesouterHTML.search(/\> *\</) ;// 在 outerHTML 上的正则表达式搜索有时会产生“错误”索引 【发布时间】:2019-11-02 05:24:24 【问题描述】:

想要通过从 table 的 outerhtml 中提取来获取 table 定义的 HTML,寻找 '> 的索引

尝试了几种模式和 match() 但没有成功。

<!DOCTYPE html>
<html>
    <head>     
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <!-- <thead> not on same line as <table> -->
        <table  id="t1" border="1">         
            <thead>
                <tr>   <th colspan="2">1</th><th colspan="3">22 </th></tr>
                <tr>    <th>1</th><th  data-rotate>22</th><th data-rotate>333</th><th>4444</th><th>5555555</th></tr>
            </thead>
            <tr><td>aaaaaaa</td><td>bbbbbbbbb</td><td>cccccccccc</td><td>ddddd<br>ddddddd</td><td>dddddddddddd</td></tr>
        </table>
        <!-- <thead> on same line as <table> -->
        <table  id="t2" border="1" >  <thead>                  
                <tr>   <th colspan="2">1</th><th colspan="3">22 </th></tr>
                <tr>    <th>1</th><th  data-rotate>22</th><th data-rotate>333</th><th>4444</th><th>5555555</th></tr>
            </thead>
            <tr><td>aaaaaaa</td><td>bbbbbbbbb</td><td>cccccccccc</td><td>ddddd<br>ddddddd</td><td>dddddddddddd</td></tr>
        </table>
        <p>
        <div id="out1"></div>
        <p>
        <div id="out2"></div>
        <script>
            /*****************************************
             * want to get the HTML for a table definition
             * by extracting <table ...> from outer html, looking
             * for the index of '> whatever <' 
             *****************************************/
            var m, t, oh, index;
            /*****************************************
             * does not work
             *****************************************/
            t = document.getElementById('t1');
            oh = t.outerHTML;
            index = oh.search(/\> *</); // what is wrong with  regex
            document.getElementById('out1').innerHTML = htmlentity(oh.substring(0, index + 1));
            /*****************************************
             * works
             *****************************************/
            t = document.getElementById('t2');
            oh = t.outerHTML;
            index = oh.search(/\> *\</);
            document.getElementById('out2').innerHTML = htmlentity(oh.substring(0, index + 1));

            function htmlentity(value) 
                value = value.replace(/&/gi, "&amp;");
                value = value.replace(/</gi, "&lt;");
                value = value.replace(/>/gi, "&gt;");
                value = value.replace(/"/gi, "&quot;");
                value = value.replace(/'/gi, "&#039;");
                return value;
            
        </script>
    </body>
</html>

```

第一个表定义“t1”不适用于我的正则表达式。 第二个表定义“t2”确实适用于我的正则表达式。

输出:

【问题讨论】:

这个正则表达式甚至应该找到什么?为什么还要使用正则表达式而不是 DOM 方法? 我只想在表格元素的结束'>'之后找到第一个html标签的开始,第一个标签应该用' 所以...类似于table.nextSibling? 【参考方案1】:

正则表达式有什么问题

正则表达式是解析 HTML 的错误工具。 (Obligatory link.) 它们可能是 HTML 解析器的一部分,但单独一个表达式不能胜任这项任务。

想要获取表格定义的 HTML

我会采取更直接的方法:表已经解析,所以只需克隆它,从克隆中删除所有文本节点,然后(如果您需要 HTML 而不仅仅是节点树)获取它的outerHTML

function extractStructure(element) 
    const clone = element.cloneNode(true);
    removeText(clone);
    return clone.outerHTML;

function removeText(element) 
    let child = element.firstChild;
    while (child) 
        let next = child.nextSibling;
        if (child.nodeType === 1)  // Element
            removeText(child);
         else if (child.nodeType === 3)  // Text
            element.removeChild(child);
        
        child = next;
    

function extractStructure(element) 
    const clone = element.cloneNode(true);
    removeText(clone);
    return clone.outerHTML;

function removeText(element) 
    let child = element.firstChild;
    while (child) 
        let next = child.nextSibling;
        if (child.nodeType === 1)  // Element
            removeText(child);
         else if (child.nodeType === 3)  // Text
            element.removeChild(child);
        
        child = next;
    

console.log(extractStructure(document.getElementById("t1")));
console.log(extractStructure(document.getElementById("t2")));
<table  id="t1" border="1">         
    <thead>
        <tr>   <th colspan="2">1</th><th colspan="3">22 </th></tr>
        <tr>    <th>1</th><th  data-rotate>22</th><th data-rotate>333</th><th>4444</th><th>5555555</th></tr>
    </thead>
    <tr><td>aaaaaaa</td><td>bbbbbbbbb</td><td>cccccccccc</td><td>ddddd<br>ddddddd</td><td>dddddddddddd</td></tr>
</table>
<!-- <thead> on same line as <table> -->
<table  id="t2" border="1" >  <thead>                  
        <tr>   <th colspan="2">1</th><th colspan="3">22 </th></tr>
        <tr>    <th>1</th><th  data-rotate>22</th><th data-rotate>333</th><th>4444</th><th>5555555</th></tr>
    </thead>
    <tr><td>aaaaaaa</td><td>bbbbbbbbb</td><td>cccccccccc</td><td>ddddd<br>ddddddd</td><td>dddddddddddd</td></tr>
</table>

【讨论】:

【参考方案2】:

在t1上正在返回线

<table  id="t1" border="1">         
    <thead>

在您的正则表达式中,您选择 /> 之后剩下的所有内容可能会贪婪吗?

试试这个index = oh.search(/\&gt;.*?/);

代码:

    const regexT = />.*?/;
    t = document.getElementById('t1');
    oh = t.outerHTML;
    index = oh.search(regexT);
    document.getElementById('out1').innerHTML = htmlentity(oh.substring(0, index + 1));
    t = document.getElementById('t2');
    oh = t.outerHTML;
    index = oh.search(regexT);
    document.getElementById('out2').innerHTML = htmlentity(oh.substring(0, index + 1));

旁注:在这种情况下,模式匹配可能不是最好的方法(参见 T.J. Crowder 的回答)

【讨论】:

为什么&gt; 被转义了?它在正则表达式中没有特殊含义。 感谢这对我有用。我使用outerHTML,因为这是源,我知道当有一个' 如果您解决了您的问题,请不要忘记投票并接受,以便遇到相同问题的人可以使用它。别忘了看看 T.J. 的评论。 @Heinz - “我使用 outerHTML 因为这是源” 不,它不是源。它是通过遍历元素并为 DOM 中的这些元素构建 HTML 创建的新字符串。这与创建表的原始源不同(如果甚至有原始源,而不是动态创建的)。 @T.J.克劳德 - 我担心我不完全明白你在告诉我什么。对我来说,重点是,只要我在外层HTML 中找到我在左“”括号之间写的所有内容,这对我来说没问题。

以上是关于outerHTML.search(/\> *\</) ;// 在 outerHTML 上的正则表达式搜索有时会产生“错误”索引的主要内容,如果未能解决你的问题,请参考以下文章

MySQL视图和自定义函数

爬取天堂图片网图片并存储

php将获取的数组变成字符串传入txt文本。。。

dvd管理系统

爬取腾讯社招职位信息

爬取腾讯社招职位信息