Regex不需要的匹配

drkbr07n  于 2023-08-08  发布在  其他
关注(0)|答案(3)|浏览(85)

我有一个标量中的HTML代码。HTML代码可以包含我想要替换的某个域的URL。例如:

my $code = <<ENDCODE;
  <img src="http://server1.olddomain.com/image1.jpg">
  <img src="http://server5.otherdomain.com/image2.jpg">
  <img src="http://server2.olddomain.com/image3.jpg">
ENDCODE

字符串
URL的服务器部分可以是任何内容(所以不一定是“www”)。我希望将所有指向www.example.com的图像URL替换为olddomain.comnewdomain.com,但前提是该图像存在于newdomain.com上。所以我不能简单地直接替换,而是需要调用一个函数(执行必要的检查)。所以我想我会做这样的事情:

$code =~ s/src=\"(.+?\.olddomain\.com\/.+?)\"/URLReplace($1)/gsie;


URLReplace是一个执行所有检查并在必要时替换URL的函数。问题是正则表达式找到两个匹配:

http://www.olddomain.com/image1.jpg


http://www.otherdomain.com/image2.jpg">\n<img src="http://www.olddomain.com/image3.jpg


当然,问题是第一个.+?捕获了下一个“. olddomain.com”之前的所有内容,在第二个匹配中,它是http://www.somedomain.com/image2.jpg">\n<img src="http://www
那么我该如何解决这个问题呢?

wlsrxk51

wlsrxk511#

如果不希望.匹配换行符,请不要使用/s
使用.通常太笼统了。如果你知道URL是用双引号括起来的,你可以用[^"]替换它:

s/src="([^"]+\.olddomain\.com\/[^"]+)"/.../

字符串

eivgtgni

eivgtgni2#

我找到了一个解决方案:
因使用

s/src=\"(.+?\.olddomain\.com\/.+?)\"/URLReplace($1)/gsie;

字符串
我应该用

s/src=\"([^\.]+?\.olddomain\.com\/.+?)\"/URLReplace($1)/gsie;


不同之处在于,我现在使用[^\.],而不是使用.(匹配任何字符),它匹配任何字符 * 但 * 点。所以它在遇到第一个点时停止匹配。

5lhxktic

5lhxktic3#

除了正则表达式,你还可以用DOM来改变HTML。Mojo::DOM支持CSS选择器来匹配属性中的子字符串。找到要更改的节点后,可以使用Mojo::URL(或任何URI lib)的功能来替换主机名:

use v5.10;
use Mojo::DOM;
use Mojo::URL;

my $code = <<~'ENDCODE';
  <img src="http://server1.olddomain.com/image1.jpg">
  <img src="http://server5.otherdomain.com/image2.jpg">
  <img src="http://server2.olddomain.com/image3.jpg">
ENDCODE

my $dom = Mojo::DOM->new($code);

my $old = ".olddomain.com";
$dom->find( "img[src*=$old]" )
    ->each( sub {
        my $url = Mojo::URL->new($_->attr('src'));
        return unless $url->host =~ m/\Q$old\E\z/;
        $url->host(  $url->host =~ s/\Q$old\E\z/\.newdomain.com/r );
        $_->attr( src => $url );
        } )
    ;

say $dom;

字符串
输出显示了域的选择性更新:

<img src="http://server1.newdomain.com/image1.jpg">
<img src="http://server5.otherdomain.com/image2.jpg">
<img src="http://server2.newdomain.com/image3.jpg">


诀窍是每个阶段都限制了效果,这样你就不会遇到你不想改变的文本。你知道你有一个img标签,其中src有你想要的子字符串,然后你知道你只处理src值,然后你知道你只处理URL的host部分。
我有很多Mojolicious Web UserAgents中DOM解析和修改的例子。

相关问题