Perl负面展望未来

时间:2012-06-18 10:37:45

标签: regex perl

这是一个小而实用的Perl代码片段:

my $content = qq{<img src='h};
if ($content =~ m{src=(?!('*)http://)}) {
   print "Match '$1'\n";
}
else {
   print "No match\n";
}

打印

Match '''

这是正面的(正面的)前面的正则表达式('*)确实被捕获并包含'。

但是,如果我用

替换第一行
my $content = qq{<img src='i};

脚本打印

Match ''

意味着尽管整个正则表达式匹配,但仍没有被捕获。

任何人都可以解释有什么区别,我怎样才能解决这个问题,以便'始终捕获'(这当然是对真实案例的简化)。

提前致谢

附录

现在这是raina77ow的全部故事。我们的想法是替换img标记中src属性的内容。以下规则适用:

  1. 如果内容以''必须以'结尾。
  2. 开头
  3. 如果内容以“必须以...结尾”开头。
  4. 内容可以不加引号。
  5. 如果内容(在可能的引用之后)以http://开头,则应保持原样,否则必须保留URL的最后一个组件(图像文件名),并且必须用smth替换前一部分。
  6. 最初我想使用以下正则表达式(实际上与你建议的相同)

    $content =~ s{<\s*img\s+(.*?)src\s*=\s*(["']*)(?!http://).*?([^/"']+)\2(\s+[^>]+)*>}
                 {'<img ' . $1 . 'src="' . 'SMTH' . $3 . '"' . $4 . '>'}sgie;
    

    但由于某种原因,它匹配字符串

    [img src ='http://qq.com/img.gif'/]

    (尖括号用方括号代替)。

    虽然它不应该因为'后跟http://。使用

    $content =~ s{<\s*img\s+(.*?)src\s*=\s*(["'])*(?!http://).*?([^/"']+)\2(\s+[^>]+)*>}
                 {'<img ' . $1 . 'src="' . 'SMTH' . $3 . '"' . $4 . '>'}sgie;
    

    也不合适,因为在这种情况下\ 2将不匹配空字符串。

    无法修复我决定寻找一些解决方法。唉...

2 个答案:

答案 0 :(得分:4)

使用强大的HTML解析器/库来应用问题中的四个规则:

use strictures;
use URI qw();
use Web::Query qw();
my $w = Web::Query->new_from_html(<<'HTML');
<html><head></head><body>
<img src='http://example.com'>
<img src="http://example.com">
<img src=http://example.com>
<img src='foo/bar/baz.png'>
<img src="foo/bar/baz.png">
<img src=foo/bar/baz.png>
</body></html>
HTML

$w->find('img')->each(sub {
    my (undef, $img) = @_;
    my $u = URI->new($img->attr('src'));
    unless ($u->scheme) {   # skip absolute URIs
        $u->path_segments('SMTH', ($u->path_segments)[-1]);
        $img->attr('src', $u);
    }
});
print $w->html;

答案 1 :(得分:1)

嗯,很容易解决它:

my $content = qq{<img src='h};
if ($content =~ m{src=('*)(?!http://)}) {
   print "Match '$1'\n";
}
else {
   print "No match\n";
}

但是解释你描述的错误(我认为这真的是Perl正则表达式引擎的错误 - 为什么('*)'h'i情况下应该有不同的匹配?)是另一个故事。 )

更新:原谅我提交给Cthulhu方式,但这段代码可能会按照您的要求执行:

sub correct { # just an example
  my $orig = shift;
  $orig =~ s/\.gif$/\.jpg/;
  return $orig;
}

my $img = "<img src='http://localhost.com/pic.gif' />";
$img =~ s{
  (< \s* img \s+ src \s* = \s*)
  (["']?)
  ([^ '">]+)
  \2
}{ 
  $1 . $2 . ( substr($3, 0, 7) eq 'http://' ?  $3  : correct $3 ) . $2
}xe;

print $img;

但是,我认为,那些说使用HTML Parser,其中任何一个更好的人都能获得最大的线索。 )