Single perl regex to remove escaped ampersands from internal href attributes, but not elsewhere
This is a more cryptic question to my curiosity than anything else. I am looking for one regex replacement that will convert entities with escaped ampersands to unescaped ampersands only inside href attributes in an html file. For instance:
<a href="http://example.com/index.html?foo=bar&baz=qux&frotz=frobnitz">
Me, myself & I</a>
Will convert to:
<a href="http://example.com/index.html?foo=bar&baz=qux&frotz=frobnitz">
Me, myself & I</a>
Now I can do this in multiple statements, but I am curious if any regex perl guru can do this in one.
The closest I've come to so far is the following regex which doesn't work because the lookbehind can't be variable length. Of course this might not work even if they are allowed, I'm not sure.
s/(?<=href=".*?)&(?=.*?")/&/g;
Thanks.
a source to share
Adapting your close proximity:
while (s/(?<=href=")([^"]*?)&/$1&/) {}
This is a deceiver; but that's one regex. The key part is non-live scanning for characters that are not a closing double quote followed by a string &
. Another observation is that given the input:
<a href="http://example.com/index.html?x=y&amp;amp;y=z">
You will exit:
<a href="http://example.com/index.html?x=y&y=z">
You must decide if this matters.
The difficulty with any non-iterative solution is that once you read " href="
" in the first match, you won't see it again for subsequent matches.
a source to share
This regex will do what you want in one line of Perl code, without an inefficient while loop (which forces the regex to start from the very beginning every time) or lookbehind:
s/((href="|\G)[^"]*?&)amp;/$1/g;
The trick is to use \ G to make the regex "remember" that it is inside the href attribute.
This regex also correctly replaces & with &
The only imperfection is that if it happens at the very beginning of the subject line, it will also be replaced. If you want to avoid this use:
s/((href="|\G(?!\A))[^"]*?&)amp;/$1/g;
a source to share
OK. First of all - the & in the hrefs is fine, so I don't understand why you want to change it - in fact the html with and in the hrefs won't be valid!
Second - if you need it - you should really use a sane HTML Parser.
The third one you want can be done quite easily, but not very pretty:
s{href="([^"]*)"}{my $q=$1; $q =~ s/\&/&/g; 'href="' . $q . '"'}eg;
But please: just because it's technically possible doesn't mean you should use it.