Perl regular expression - search and replace
I can't get my head around perl search and replace in a string, or regular expressions. Can someone help, please?
I've got a file that contains HTML and I want to change the class of certain items if they a present in given set (in this case a hash table or validated fields that failed validation). So I've got, for example, the following:
<input name="RMAProcess" type="radio" class="inputnormal" value="Good">
and I want to change the "inputnormal" class to the value "inputpink". What I'm tryin开发者_开发百科g to do is make it so that I match the whole string nomatter in which order the properties appear, so that, for example, the following will also match:
<input name="RMAProcess" type="radio" value="Good" class="inputnormal">
This is because Dreamweaver will sometimes mess around with the order of properties in the HTML during editing, so I can't rely on fixed positions for them.
So I end up with something that doesn't work, such as:
foreach $key ( keys %FAILED ) {
$infile =~ s/<input type="radio" name="$key" value="$VALUES{$key}" class="([a-zA-Z]+)"/$1inputpink"/gi;
}
Can anyone help me out with this?
Thanks.
Edit: ok, this kind-of works, assuming the properties inside the tags don't move around:
foreach $key ( keys %FAILED ) {
$infile =~ s/(<.{4,10}\ type="radio" name="$key".{1,60}class=")([a-zA-Z]+)"/$1inputpink"/gi;
}
That will have to do for now! Thanks for all your responses.
You should use an HTML parser to parse HTML. I use HTML::TreeBuilder.
Instead of matching the entire input tag, I recommend matching the class part. This regex should work I think....
my $htmlLine = "<input name=\"RMAProcess\" type=\"radio\" class=\"inputnormal\" value=\"Good\">";
$htmlline =~s/class="inputnormal"/class="inputpink"/i;
If you have a choice,
$ cat file
<input name="RMAProcess" type="radio" class="inputnormal" value="Good">
<input name="RMAProcess" type="radio" value="Good" class="inputnormal">
$ ruby -ne 'print $_.gsub(/(.*class=")(.[^"]*)(".*)/, "\\1inputpink\\3" ) ' file
<input name="RMAProcess" type="radio" class="inputpink" value="Good">
<input name="RMAProcess" type="radio" value="Good" class="inputpink">
its just substitution with back references, so the regex could be used in a Perl context as well...
If you need to make sure there is name="", type="", value=""
, then use if
eg
ruby -ne 'print $_.gsub(/(.*class=")(.[^"]*)(".*)/, "\\1inputpink\\3" ) if /name=/&&/type=/&&/value=/' file
Probably easier to do this in two steps:
Split the line into attributes and check if "name=X" and "type=y", by creating a hash on attributes or running several reg.exps.
If you then want to change the line, you can just replace class with a simple reg.exp
If you can't install any module, you can try something like :
#!/usr/bin/perl
use Modern::Perl;
my %FAILED = (RMAProcess => 'Good');
while (my $line = <DATA>) {
chomp($line);
foreach my $key ( keys %FAILED ) {
if ($line =~ /type="radio"/ && $line =~ /name="$key"/ && $line =~/value="$FAILED{$key}"/) {
$line =~ s/class="([a-zA-Z]+)"/class="inputpink"/;
}
}
say $line;
}
__DATA__
<input name="RMAProcess" type="radio" class="inputnormal" value="Good">
<input name="RMAProcess" type="radio" value="Good" class="inputnormal">
output:
<input name="RMAProcess" type="radio" class="inputpink" value="Good">
<input name="RMAProcess" type="radio" value="Good" class="inputpink">
精彩评论