【问题标题】:Regex select all text between tags正则表达式选择标签之间的所有文本
【发布时间】:2011-11-02 07:05:31
【问题描述】:

选择 2 个标签之间的所有文本的最佳方法是什么 - 例如:页面上所有“<pre>”标签之间的文本。

【问题讨论】:

  • 如果你喜欢python,最好的方法是使用像“Beautiful Soup”这样的html解析器......
  • 最好的方法是使用 XML/HTML 解析器。
  • 一般来说,用正则表达式解析html不是个好办法:stackoverflow.com/questions/1732348/…
  • 不要使用正则表达式解析标签之间的文本,因为任意嵌套的标签会使 HTML 不规则。匹配标签似乎没问题。 /<div>.*?<\/div>/.exec("<div><div></div></div>")

标签: html regex html-parsing


【解决方案1】:

您可以使用"<pre>(.*?)</pre>",(将 pre 替换为您想要的任何文本)并提取第一组(对于更具体的说明,请指定一种语言),但这假定您拥有非常简单且有效的 HTML 的简单概念。

正如其他评论者所建议的那样,如果您正在做一些复杂的事情,请使用 HTML 解析器。

【讨论】:

  • 这不会选择标签之间的文本,它包括标签。
  • 您需要使用 () 抓取选择
  • 对于多行标签:(.+)((\s)+(.+))+
  • 这仍然具有可见性,因此:如果您在尝试 <pre>(.*?)<\/pre> 后仍然看到 <pre> 标签,那是因为您正在查看完整匹配而不是 (.*? ) 捕获组。听起来很俗气,但我一直认为“括号 = 一对小偷”,因为除非 ( 后跟 ?,如 (?:(?>,每场比赛都会有两个捕获:1 代表完整比赛和 1对于捕获组。每组额外的括号都会添加一个额外的捕获。您只需要知道如何以您正在使用的任何语言检索这两个捕获。
  • 你需要转义/
【解决方案2】:

标签可以在另一行完成。这就是需要添加\n 的原因。

<PRE>(.|\n)*?<\/PRE>

【讨论】:

  • 在处理多行 HTML 标记时添加(.|\n)*? 的重要一点。仅当 HTML 标记位于同一行时,所选答案才有效。
  • (.|\n|\r\n)*? 用于 Windows 行尾
  • 永远不要使用(.|\n)*? 来匹配任何字符。始终使用 .s(单行)修饰符。或[\s\S]*? 解决方法。
  • 我想在 notepad++ 中选择代码 cmets,所以使用这个答案我想出了/\*(.|\n)*?\*/,它完成了这项工作——谢谢
【解决方案3】:

这是我会使用的。

(?<=(<pre>))(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|`~]| )+?(?=(</pre>))

基本上它的作用是:

(?&lt;=(&lt;pre&gt;)) 选择前必须加上&lt;pre&gt; 标签

(\w|\d|\n|[().,\-:;@#$%^&amp;*\[\]"'+–/\/®°⁰!?{}|~]| ) 这只是我要应用的正则表达式。在这种情况下,它选择方括号中示例中列出的字母或数字或换行符或一些特殊字符。管道字符| 仅表示“OR”。

+? 加字符状态以选择上述一项或多项-顺序无关紧要。 问号将默认行为从“贪婪”更改为“不贪婪”。

(?=(&lt;/pre&gt;)) 选择必须附加&lt;/pre&gt; 标签

根据您的用例,您可能需要添加一些修饰符,例如 (im)

  • i - 不区分大小写
  • m - 多行搜索

这里我在 Sublime Text 中执行了这个搜索,所以我不必在我的正则表达式中使用修饰符。

Javascript 不支持lookbehind

上面的示例应该适用于 PHP、Perl、Java 等语言...
然而,Javascript 不支持后视,所以我们必须忘记使用 `(?))` 并寻找某种解决方法。也许简单地从我们的结果中为每个选择去掉前四个字符,就像这里一样 https://stackoverflow.com/questions/11592033/regex-match-text-between-tags

还要查看JAVASCRIPT REGEX DOCUMENTATION 中的非捕获括号

【讨论】:

  • 请注意,您需要使用 ` 转义单引号/双引号字符,以便将正则表达式放入字符串中。
【解决方案4】:

要排除定界标签:

(?<=<pre>)(.*?)(?=</pre>)

(?&lt;=&lt;pre&gt;)&lt;pre&gt; 之后查找文本

(?=&lt;/pre&gt;)&lt;/pre&gt; 之前查找文本

结果将在pre标签内显示

【讨论】:

  • 使用这个的人看看@krishna thakor 的答案,这也可以考虑内容标签之间是否有新行
  • 这对我有帮助(不需要考虑换行符)。谢谢。
【解决方案5】:

使用下面的模式来获取元素之间的内容。将 [tag] 替换为您希望从中提取内容的实际元素。

<[tag]>(.+?)</[tag]>

有时标签会有属性,比如anchor标签有href,然后使用下面的模式。

 <[tag][^>]*>(.+?)</[tag]>

【讨论】:

  • 尝试第一个示例为 '(.+?)' 并按预期工作。但我没有第二个结果。
  • 这不起作用。 &lt;[tag]&gt; 将匹配 &lt;t&gt;&lt;a&gt;&lt;g&gt;
  • @MA-Maddin - 我想你错过了Replace [tag] with the actual element you wish to extract the content from 部分。
  • 哦,是的。这些[] 应该完全省略。这会更清楚,因为它们在 RegEx 中的含义以及人们首先扫描代码并在之后阅读文本的事实;)
【解决方案6】:

这个答案假设支持环顾四周!这使我能够识别开始和结束标签对之间的所有文本。这就是“>”和“

(?<=>)([\w\s]+)(?=<\/)

我使用这个 HTML 片段在https://regex101.com/ 中对其进行了测试。

<table>
<tr><td>Cell 1</td><td>Cell 2</td><td>Cell 3</td></tr>
<tr><td>Cell 4</td><td>Cell 5</td><td>Cell 6</td></tr>
</table>

这是一个由三部分组成的游戏:向后看、内容和向前看。

(?<=>)    # look behind (but don't consume/capture) for a '>'
([\w\s]+) # capture/consume any combination of alpha/numeric/whitespace
(?=<\/)   # look ahead  (but don't consume/capture) for a '</'

我希望这是 10 岁的开始。运气。

【讨论】:

  • 谢谢。这不仅是一个更好的答案,而且是 regex101 站点的一个很好的链接。点赞! ?
  • 上面的正则表达式非常好,但它只会返回找到的第一个匹配项,不会覆盖特殊字符或新行。为此,请改用以下内容:myString.match(/(?&lt;=&gt;)([\w\s\-\!@#$%^&amp;*()_+|~={}[]:";'?,.\/]+)(?=
【解决方案7】:

您不应该尝试使用正则表达式解析 html,请参阅 this question 以及结果如何。

用最简单的话来说,html不是正则语言,所以你不能用正则表达式完全解析。

话虽如此,当没有嵌套类似的标签时,您可以解析 html 的子集。因此,只要介于 and 之间的任何内容不是该标签本身,它就会起作用:

preg_match("/<([\w]+)[^>]*>(.*?)<\/\1>/", $subject, $matches);
$matches = array ( [0] => full matched string [1] => tag name [2] => tag content )

一个更好的主意是使用解析器,如原生 DOMDocument,加载您的 html,然后选择您的标签并获取可能看起来像这样的内部 html:

$obj = new DOMDocument();
$obj -> load($html);
$obj -> getElementByTagName('el');
$value = $obj -> nodeValue();

由于这是一个合适的解析器,它可以处理嵌套标签等。

【讨论】:

  • 只是想说我有点不安,这仍然在收集反对票,而它是在正则表达式旁边提供适当解决方案的唯一答案,我还添加了充分的警告,它是可能不是正确的方法......请至少评论一下我的回答有什么问题。
  • 该问题未使用php 标记。不知道 PHP 是如何出现的...
  • @trincot 这是 7 年前的事了,所以我不记得了。在任何情况下,它都是用正则表达式和解析器解决问题的一个例子。正则表达式很好,而php正是我当时所熟悉的。
  • 我明白了,我看到了您的第一条评论,并认为这可以解释一些反对意见。
  • "/]*>(.*?)/" 在 python 中不匹配
【解决方案8】:

这似乎是我发现的最简单的正则表达式

(?:<TAG>)([\s\S]*)(?:<\/TAG>)
  1. 从匹配项中排除开始标记 (?:&lt;TAG&gt;)
  2. 在匹配中包含任何空格或非空格字符([\s\S]*)
  3. 从匹配项中排除结束标记 (?:&lt;\/TAG&gt;)

【讨论】:

    【解决方案9】:

    试试这个....

    (?<=\<any_tag\>)(\s*.*\s*)(?=\<\/any_tag\>)
    

    【讨论】:

    • 请注意,JavaScript 不支持向后看。
    • 当然,但是这个正则表达式是用于 Java 的。谢谢你的来信。
    【解决方案10】:

    var str = "Lorem ipsum <pre>text 1</pre> Lorem ipsum <pre>text 2</pre>";
        str.replace(/<pre>(.*?)<\/pre>/g, function(match, g1) { console.log(g1); });

    由于接受的答案没有javascript代码,所以添加:

    【讨论】:

      【解决方案11】:

      preg_match_all(/&lt;pre&gt;([^&gt;]*?)&lt;\/pre&gt;/,$content,$matches) 这个正则表达式将选择标签之间的每一个。不管它是否在新行中(使用多行。

      【讨论】:

        【解决方案12】:

        在 Python 中,设置 DOTALL 标志将捕获所有内容,包括换行符。

        如果指定了 DOTALL 标志,则匹配任何字符,包括换行符。 docs.python.org

        #example.py using Python 3.7.4  
        import re
        
        str="""Everything is awesome! <pre>Hello,
        World!
            </pre>
        """
        
        # Normally (.*) will not capture newlines, but here re.DOTATLL is set 
        pattern = re.compile(r"<pre>(.*)</pre>",re.DOTALL)
        matches = pattern.search(str)
        
        print(matches.group(1))
        

        python example.py

        Hello,
        World!
        

        捕获文档中所有开始和结束标记之间的文本

        要捕获文档中所有开始和结束标记之间的文本,finditer 很有用。在下面的示例中,字符串中存在三个开始和结束&lt;pre&gt; 标签。

        #example2.py using Python 3.7.4
        import re
        
        # str contains three <pre>...</pre> tags
        str = """In two different ex-
        periments, the authors had subjects chat and solve the <pre>Desert Survival Problem</pre> with a
        humorous or non-humorous computer. In both experiments the computer made pre-
        programmed comments, but in study 1 subjects were led to believe they were interact-
        ing with another person. In the <pre>humor conditions</pre> subjects received a number of funny
        comments, for instance: “The mirror is probably too small to be used as a signaling
        device to alert rescue teams to your location. Rank it lower. (On the other hand, it
        offers <pre>endless opportunity for self-reflection</pre>)”."""
        
        # Normally (.*) will not capture newlines, but here re.DOTATLL is set
        # The question mark in (.*?) indicates non greedy matching.
        pattern = re.compile(r"<pre>(.*?)</pre>",re.DOTALL)
        
        matches = pattern.finditer(str)
        
        
        for i,match in enumerate(matches):
            print(f"tag {i}: ",match.group(1))
        

        python example2.py

        tag 0:  Desert Survival Problem
        tag 1:  humor conditions
        tag 2:  endless opportunity for self-reflection
        

        【讨论】:

          【解决方案13】:

          要选择我喜欢的前标记之间的所有文本

          preg_match('#&lt;pre&gt;([\w\W\s]*)&lt;/pre&gt;#',$str,$matches);

          $matches[0] 将得到包含

           标记 的结果
          

          $matches[1] 将包含

           中的所有内容。
          

          DomDocument 不能在需要在搜索标签中获取带有标签详细信息的文本的情况下工作,因为它会去除所有标签,nodeValue 和 textContent 将只返回没有标签和属性的文本。

          【讨论】:

            【解决方案14】:

            您可以使用Pattern pattern = Pattern.compile( "[^&lt;'tagname'/&gt;]" );

            【讨论】:

              【解决方案15】:

              我使用这个解决方案:

              preg_match_all( '/<((?!<)(.|\n))*?\>/si',  $content, $new);
              var_dump($new);
              

              【讨论】:

                【解决方案16】:
                (?<=>)[^<]+
                

                记事本++

                >([^<]+)
                

                对于 AutoIt(选项 返回全局匹配数组)。

                 (?=>([^<]+))
                

                https://regex101.com/r/VtmEmY/

                【讨论】:

                  【解决方案17】:
                  const content = '<p class="title responsive">ABC</p>';
                  const blog = {content};
                  const re = /<([^> ]+)([^>]*)>([^<]+)(<\/\1>)/;
                  const matches = content.match(re);
                  console.log(matches[3]);
                  

                  matches[3] 是内容文本,它适用于任何带有类的标签名称。 (不支持嵌套结构)

                  【讨论】:

                    【解决方案18】:

                    对于多行:

                    <htmltag>(.+)((\s)+(.+))+</htmltag>
                    

                    【讨论】:

                      【解决方案19】:

                      在 Javascript(以及其他)中,这很简单。它涵盖了属性和多行:​​

                      /<pre[^>]*>([\s\S]*?)<\/pre>/
                      

                      【讨论】:

                        【解决方案20】:
                        <pre>([\r\n\s]*(?!<\w+.*[\/]*>).*[\r\n\s]*|\s*[\r\n\s]*)<code\s+(?:class="(\w+|\w+\s*.+)")>(((?!<\/code>)[\s\S])*)<\/code>[\r\n\s]*((?!<\w+.*[\/]*>).*|\s*)[\r\n\s]*<\/pre>
                        

                        【讨论】:

                        • 请用文字介绍/解释你的答案。
                        猜你喜欢
                        • 1970-01-01
                        • 2023-03-28
                        • 2011-05-20
                        • 2011-03-18
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多