单个perl正则表达式用于从href属性内部删除转义的&符号,但不能从其他地方删除

时间:2009-05-19 01:54:19

标签: regex perl

这对我的好奇心而言比其他任何问题都更令人困惑。我正在寻找一个正则表达式替换,它将实体转义的&符号转换为仅在html文件中的href属性内的未转义的&符号。例如:

<a href="http://example.com/index.html?foo=bar&amp;baz=qux&amp;frotz=frobnitz">
Me, myself &amp; I</a>

会转换为:

<a href="http://example.com/index.html?foo=bar&baz=qux&frotz=frobnitz">
Me, myself &amp; I</a>

现在,我可以在几个陈述中做到这一点,但我很好奇是否有任何perl正则表达式专家可以在一个中完成。

我到目前为止最接近的是以下正则表达式无效,因为lookbehinds不能是可变长度。当然,即使允许它也可能不起作用,我不确定。

s/(?<=href=".*?)&amp;(?=.*?")/&/g;

感谢。

4 个答案:

答案 0 :(得分:3)

调整近似值:

while (s/(?<=href=")([^"]*?)&amp;/$1&/) {}

这是骗子;但它是一个单一的正则表达式。关键部分是非贪心扫描,这些字符不是关闭双引号,后跟&amp;字符串。要做的另一个观察是给出输入:

<a href="http://example.com/index.html?x=y&amp;amp;amp;y=z">

你会离开:

<a href="http://example.com/index.html?x=y&y=z">

你必须决定这是否重要。

任何非迭代解决方案的难点在于,一旦你在第一场比赛中看到“href="”,你就不会再看到它了。

答案 1 :(得分:2)

这个正则表达式将在一行Perl代码中执行您想要的操作,而没有低效的while循环(这使得正则表达式从每次开始开始)或者是lookbehind:

s/((href="|\G)[^"]*?&)amp;/$1/g;

诀窍是使用\ G使正则表达式“记住”它在href属性中。

这个正则表达式也正确地取代了&amp; amp; amp;与&amp; amp;

唯一不完美的是,如果&amp;发生在主题字符串的最开头,它也将被替换。如果您想避免这种情况,请使用:

s/((href="|\G(?!\A))[^"]*?&)amp;/$1/g;

答案 2 :(得分:1)

不要尝试使用正则表达式解析非常规语言。从CPAN获取HTML解析器,然后根据您需要的元素进行操作。

答案 3 :(得分:1)

行。首先 - &amp; amp; amp;在hrefs中完全没问题,所以我不明白你为什么要改变它 - 实际上是html with&amp;在hrefs中无效!

第二 - 如果你需要任何东西 - 你真的应该使用一些合理的HTML解析器。

第三,你想要的很容易,但不是很好:

s{href="([^"]*)"}{my $q=$1; $q =~ s/\&amp;/&/g; 'href="' . $q . '"'}eg;

但是,请注意:技术上可行的事实并不意味着你应该使用它。