tags:

views:

775

answers:

3

I'm looking for a single line regex which does the following:

Given a HTML tag with the "name" attribute, I want to replace it with my own attribute. If that tag lacks the name attribute, I want to implant my own attribute. The result should look like this:

<IMG name="img1" ...> => <IMG name="myImg1" ...>
<IMG ...> => <IMG name="myImg1" ...>

Can this be done with a single line regex?

A: 

If, like in your example, the name attribute is always the first one inside the IMG tag, then it's very easy. Search for

<(?!/)(/w+)\s+(name="[^"]+")?

and replace with

<\1 name="myImg1"

but I doubt that this is what you really want.

If the name attribute can occur in other positions, it gets more difficult.

Tim Pietzcker
Well, since I edit general HTML files, I cannot be sure the attribute is the first one. Actually, I'm quite sure it's not.
Moshe
+1  A: 

This isn't a perfect solution, the spacing and position within the tag may not be exactly what you want, but it does accomplish the goals. This is with a perl regex, but there's nothing particular perl-specific about it.

s/(&lt;IMG)((\s+[^&gt;]*)name="[^"]*")?(.*)/$1$3 name="myID"$4/g
Sean
This almost works. It fails when the "name" tag isn't the first one.
Moshe
That is untrue. Did you test it? the (\s+[^>]) covers preceding attributes.
Sean
+2  A: 

The trick is to match every complete "attribute=value" pair, but capture only the ones whose attribute name isn't "name". Then plug in your own "name" attribute along with all the captured ones.

s/<IMG
  ((?:\s+(?!name\b)\w+="[^"]+")*)
  (?:\s+name="[^"]+")?
  ((?:\s+(?!name\b)\w+="[^"]+")*)
  >
 /<IMG name="myName"$1$2>
 /xg;
Alan Moore
This is a better solution than mine, but it does move the name attribute to the start if it exists later in the tag.
Sean
Is that a problem? AFAIK, the order of the attributes doesn't matter.
Alan Moore