开发者

Perl regular expression - search and replace

开发者 https://www.devze.com 2023-02-20 17:27 出处:网络
I can\'t get my head around perl search and replace in a string, or regular expressions.Can someone help, please?

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:

  1. Split the line into attributes and check if "name=X" and "type=y", by creating a hash on attributes or running several reg.exps.

  2. 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">
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号