作为解析脚本的一部分,我正在尝试转换这样的字符串:
<a href="http://www.web.com/%20Special%20event%202013%20%282%29.pdf">
到
<a href="http://www.web.com/%20Special%20event%202013%20(2).pdf">
右括号的正则表达式正常
perl -i -pe "s~(href\=\/?[\"\']\.\.\/$i\-(?:(?!%29).)*)%29([^\"\']*[\"\'])~\1)\2~g" "$pageName".html
给我
<a href="http://www.web.com/%20Special%20event%202013%20%282).pdf">
问题与左括号的等效正则表达式相矛盾:
perl -i -pe "s~(href\=\/?[\"\']\.\.\/$i\-(?:(?!%28).)*)%28([^\"\']*[\"\'])~\1(\2~g" "$pageName".html
只返回两组之间没有任何内容:
<a href="http://www.web.com/%20Special%20event%202013%202%29.pdf">
逃避(用反斜杠替换(或两个)没有效果。如果我将它包装在其他一些字符中(比如〜\ 1#(#\ 2~g),括号仍然消失(给我%20) ## 2%29)。
然而,如果在绝望中我将7个括号添加到替换中,它就可以工作。
perl -i -pe "s~(href\=\/?[\"\']\.\.\/$i\-(?:(?!%28).)*)%28([^\"\']*[\"\'])~\1(((((((\L\2~g" "$pageName".html
输出
<a href="http://www.web.com/%20Special%20event%202013%20(2%29.pdf">
有人可以理解这一点。
答案 0 :(得分:3)
以下可能会有所帮助或至少提供一些方向。它适用于Perl版本10及更高版本。
use strict;
use warnings;
use v5.10.0; # For regex \K
use URI::Escape;
my $string = '<a href="http://www.web.com/%20Special%20event%202013%20%282%29.pdf">';
$string =~ s/.+2013%20\K([^.]+)(?=\.pdf)/uri_unescape($1)/e;
print $string;
输出:
<a href="http://www.web.com/%20Special%20event%202013%20(2).pdf">
将足够的日期和空格(%20
)作为锚,然后使用\K
来* K * eep全部。然后捕获URI编码的文本,稍后将其解码并用作替换文本。
答案 1 :(得分:0)
我在理解你的正则表达式时遇到了一些问题,但这可能会有效:
perl -pe "s~(href\s*=\s*\"[^\"]*)%28(.*?)%29~\$1(\$2)~g" input
答案 2 :(得分:0)
您拥有的模式与您显示的字符串不匹配。它匹配看起来像
的东西<a href=/"../$i-xxxxxxxxxxxxxxx%29xxxxxxxxxx">
带有文字点,以及$i
包含的内容。
另外,关于你替换的几点:
不要转义不需要转义的字符。可能需要一些经验才能知道你需要逃避哪些字符,但使用~
作为分隔符的主要目的是避免在正则表达式中转义斜杠,所以至少你可以避免这种情况。
请勿在替换字符串中使用\1
,\2
等。 Perl非常努力地完成这项工作,但通常在Perl中,这些序列意味着插入字符\x01
和\x02
。使用$1
和$2
。
所以你的正则表达式可以写成
s~(href=/?["']\.\./$i-(?:(?!%29).)*)%29([^"']*["'])~$1)$2~;
但是它仍然没有“正常工作”你给的字符串,这看起来像
<a href=/"../$i-xxxxxxxxxxxxxxx%282%29xxxxxxxxxx">
再次,包含$i
中的任何内容。我完全不了解href
属性值之前的可选斜杠:它是无效的HTML。
但是,使用第一个正则表达式匹配的字符串,你的第二个正常工作,正确替换开括号,所以我无法猜出问题可能是什么。
通常无需验证整个字符串。你可以只替换你感兴趣的部分。所以我会写一些类似
的东西s/(href="[^"]+)%28(\d+)%29(\.pdf")/$1($2)$3/;
在您给出的字符串上工作正常,并立即替换打开和关闭括号。