2

这是一个小而实用的 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. 如果内容(可能的引用之后)以 http:// 开头,则应保持原样,否则 URL 的最后一个组成部分(图像文件名)必须保留,并且前面的部分必须替换为 smth。

最初我想使用以下正则表达式(实际上与您建议的相同)

$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 将不匹配空字符串。

无法解决这个问题,我决定寻找一些解决方法。唉...

4

2 回答 2

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;
于 2012-06-18T13:24:02.807 回答
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 的人,我认为他们中的任何一个都得到了最大的线索。)

于 2012-06-18T10:51:38.717 回答