2013-05-08 211 views
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)。

如果在绝望情况下, 7个parenthesises进入替代,它的工作原理。

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

你有你展示在所有的字符串不匹配的模式。它匹配的东西,看起来像

<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/; 

其中您所提供的字符串工作正常,并且一次更换打开和关闭括号。

+0

谢谢。这是一般的好建议。我试图在发布之前简化问题,但显然很大程度上错过了该标记。我回去清理了一些东西,并加入了更多调试,最终将问题追溯到我的脚本中的另一个流氓替换 – monototo 2013-05-09 02:41:59

+0

澄清了几点:$ i是一个变量,因为它位于shell脚本中。其次,我知道可选的斜杠不是有效的HTML,我只是试图容纳WYSISYG编辑器所做的任何事情。归根结底,尽管你给了它的批判性评估使我有了正确的思维方式,可以多次重新评估这种情况,直到我明白为止。谢谢! – monototo 2013-05-09 02:47:22

+0

我收集到'$ i'是一个shell变量,但是我无法将你的正则表达式与你声称匹配的字符串进行协调。我尝试过的匹配第一个模式的任何字符串也会匹配第二个模式,所以我无法复制您的问题。这里有一个很好的例子,把整个东西写成一个Perl脚本,而不是一个不确定的shell和Perl的混合体,在那里没有人确定应该有多少反斜杠。 Perl比任何shell都要多得多,你应该专注于彻底的学习。 – Borodin 2013-05-09 02:59:23

3

也许下面将是有益的,或者至少提供一些方向。这会l在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为* ķ * EEP这一切。然后捕获URI编码的文本,稍后将其解码并用作替换文本。

+0

@Borodin - 良好的编辑;谢谢。 – Kenosis 2013-05-08 04:48:35

+0

感谢这个答案,原来问题出在我的脚本的其他地方(另一个替代方案是删除parentesis) - 但\ K是一个方便的操作员添加到武库。 – monototo 2013-05-09 02:40:48

+0

@monototo - 非常欢迎您!好,你发现这个问题... – Kenosis 2013-05-09 04:30:01

0

我有一些问题了解你的正则表达式,但是这可能工作:

perl -pe "s~(href\s*=\s*\"[^\"]*)%28(.*?)%29~\$1(\$2)~g" input