这是一个小而实用的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属性的内容。以下规则适用:
最初我想使用以下正则表达式(实际上与你建议的相同)
$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将不匹配空字符串。
无法修复我决定寻找一些解决方法。唉...
答案 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,其中任何一个更好的人都能获得最大的线索。 )