为什么在perl正则表达式组中不能进行贪婪匹配

时间:2017-07-11 20:58:44

标签: regex perl

我试图仅使用perl正则表达式来获取html中的body标签(因此不要包含实际的body标签,因此使用组将标签丢弃到变量)。 以下是一些简短的测试科目:

<body>test1</body>
<body style="bob">test2</body>

首先,我尝试的简单版本是:

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

返回测试1和空字符串 所以我试过了:

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

现在两个测试都给出了结果,但当然有垃圾:&#34;&gt; test1&#34;和&#34;风格=&#34;摆锤&#34;&GT; TEST2&#34;

我已尝试在第一个版本中使用贪婪匹配的每个变体,例如:(?<=<body.*>).*(?=</body>)} 但它根本行不通!每次我把*放在那里我都会遇到错误。有人能帮忙吗?

4 个答案:

答案 0 :(得分:1)

  

我试图只抓取BETWEEN身体标签

在那种情况下:

#!/usr/bin/env perl

use strict;
use warnings;

while (my $line = <DATA>) {
    if ($line =~ m{ <body [^>]*> (.+) </body> }xs) {
        print "[$1]\n";
    }
}

__DATA__
<body>test1</body>
<body style="bob">test2</body>
<!-- <body class="one"> --><body>This is why you should use an HTML parser</body>

输出:

[test1]
[test2]
[ --><body>This is why you should use an HTML parser]

答案 1 :(得分:1)

您正在寻找

while ($html =~ / <body[^>]*> ( (?: (?! </body\b ). )* ) /sxg) {
   say $1;
}

答案 2 :(得分:0)

我不认为使用$&是有效的。就个人而言,我使用捕获组 但这很好用。

/<(body)(?:\s+(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!\/>)[^>])?)+)?\s*>\K[\S\s]*?(?=<\/\1\s*>)/

https://regex101.com/r/EkPkLb/1

扩展

 <
 ( body )                      # (1)
 (?:
      \s+ 
      (?>
           " [\S\s]*? "
        |  ' [\S\s]*? '
        |  (?:
                (?! /> )
                [^>] 
           )?
      )+
 )?
 \s* >
 \K 
 [\S\s]*? 
 (?= </ \1 \s* > )

请注意,要真正找到特定的标签,您必须使用所有的 之前的标签通过(*SKIP)(?!),否则您的标签可以嵌入到内部 脚本文字,评论或隐形内容。

我不会太担心它 如果您有兴趣,我可以发布一个相当大的正确的正则表达式,
但我怀疑你是否感兴趣。

答案 3 :(得分:-1)

为数据选择最佳模式取决于身体标记中包含的字符类型。另外一个考虑因素是您是否希望以效率或最小内存为目标。

这些是您的案例的一些合适的(或不是)模式:

  

93步~<body[^>]*>\K.*(?=</body>)~ #no捕获组,没有新行匹配
  105步~<body[^>]*>\K[\S\s]*?(?=</body>)~ #no捕获组,换行符匹配
  87步~<body[^>]*>(.*)</body>~ #capture组,没有换行符   96步~<body[^>]*>([\S\s]*?)</body>~ #capture group,换行符匹配

这是一个Pattern Demo,其中包含三个示例,用于显示正文字符在正文中的影响。