0

作为解析脚本的一部分,我正在尝试像这样转换字符串:

<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)。

但是,如果我绝望地在替换中添加了七个括号,它就可以了。

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">

有人可以理解这一点。

4

3 回答 3

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 编码文本,稍后将其解码并用作替换文本。

于 2013-05-08T03:06:49.370 回答
0

我在理解您的正则表达式时遇到了一些问题,但这可能有效:

 perl -pe "s~(href\s*=\s*\"[^\"]*)%28(.*?)%29~\$1(\$2)~g" input
于 2013-05-08T03:27:21.687 回答
0

您拥有的模式与您显示的字符串完全不匹配。它匹配看起来像的东西

<a href=/"../$i-xxxxxxxxxxxxxxx%29xxxxxxxxxx">

带有文字点,以及包含的任何$i内容。

另外,关于你的替换的几点:

  • 不要转义不需要转义的字符。在不检查需要转义的字符的情况下可能需要一些经验才能知道,但~用作分隔符的主要目的是避免在正则表达式中转义斜杠,因此至少您可以避免这种情况。

  • 不要在替换字符串中使用\1,等。\2Perl 非常努力地完成这项工作,但通常在 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/;

它适用于您提供的字符串,并同时替换左括号和右括号。

于 2013-05-08T04:32:31.617 回答