我有一个标量中的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
。
那么我该如何解决这个问题呢?
3条答案
按热度按时间wlsrxk511#
如果不希望
.
匹配换行符,请不要使用/s
。使用
.
通常太笼统了。如果你知道URL是用双引号括起来的,你可以用[^"]
替换它:字符串
eivgtgni2#
我找到了一个解决方案:
因使用
字符串
我应该用
型
不同之处在于,我现在使用
[^\.]
,而不是使用.
(匹配任何字符),它匹配任何字符 * 但 * 点。所以它在遇到第一个点时停止匹配。5lhxktic3#
除了正则表达式,你还可以用DOM来改变HTML。Mojo::DOM支持CSS选择器来匹配属性中的子字符串。找到要更改的节点后,可以使用Mojo::URL(或任何URI lib)的功能来替换主机名:
字符串
输出显示了域的选择性更新:
型
诀窍是每个阶段都限制了效果,这样你就不会遇到你不想改变的文本。你知道你有一个
img
标签,其中src
有你想要的子字符串,然后你知道你只处理src
值,然后你知道你只处理URL的host
部分。我有很多Mojolicious Web UserAgents中DOM解析和修改的例子。