为什么我的嵌套外观在我的Perl替换中没有正常工作?

时间:2011-10-10 13:02:04

标签: perl substitution lookahead

我有一个Perl替换,它将超链接转换为小写:

's/(?<=<a href=")([^"]+)(?=")/\L$1/g'

我希望替换忽略任何以哈希开头的链接,例如我希望它将<a href="FooBar/Foo.bar">Foo Bar</a>中的路径更改为小写但如果遇到<a href="#Bar">Bar</a>则跳过。

嵌套前瞻指示它跳过这些链接对我来说无法正常工作。这是我写过的单行内容:

perl -pi -e 's/(?<=<a href=" (?! (?<=<a href="#) ) )([^"]+)(?=")/\L$1/g' *;

有人能暗示我这个替换出错的地方吗?它执行得很好,但没有做任何事情。

2 个答案:

答案 0 :(得分:1)

尽可能接近,如果您添加链接中的第一个字符可能不是哈希#或双引号的条件,那么您的初始正则表达式将正常工作。 [^#"]

s/(?<=<a href=")([^#"][^"]+)(?=")/\L$1/gi;

如果您的链接不以哈希开头,例如<a href="FooBar/Foo.bar#BarBar">Foo Bar</a>,它变得稍微复杂一些:

s{(?<=<a href=")([^#"]+)(#[^"]+)*(?=")}{ lc($1) . ($2 // "") }gei;

我们现在必须评估替换,否则当可选的锚引用不存在时,我们会得到未定义的变量警告。

答案 1 :(得分:1)

从我看到的内容来看,你不需要环顾四周

use 5.010;
...

s/<a \s+ href \s* = \s* "\K([^#"][^"]*)"/\L$1"/gx;

\K意味着“保持”前面的一切。它金额到可变长度的后视。

perlre

  

由于各种原因,K可能比等效的(?<=...)构造更有效,并且在您希望有效地删除字符串中的其他内容的情况下,它尤其有用。