Reputation: 165
I want to do a global regex replace, where the replacement is conditional upon some logic that can't be put in a regular expression. For example:
while ( $var =~ /<IF OPERATOR="(.+?)" VALUE="(.+?)"\/>/g ) {
my $operator = $1;
my $value = $2;
if ( $operator eq 'true' && $hash{ $value } ) {
# replace the entire <IF/>
}
if ( $operator eq 'false' && ! $hash{ $value } ) {
# replace the entire <IF/>
}
}
How do I do the # replace bit? Thanks for any advice.
Upvotes: 3
Views: 299
Reputation: 126722
Your refusal to give any real data for this question, or to describe what changes you want, makes it very difficult to demonstrate the workability of a solution.
However it looks like you need an executable replacement, which has the /e
modifier.
Take a look at this code. I have added another pair of parentheses to the regex so that the entire pattern is captured as well as the two attributes. The actual replacement string is put into $replacement
and returned by the block.
$string =~ s{(<IF OPERATOR="([^"]+)" VALUE="([^"]+)"/>)}{
my $replacement = $1;
my $operator = $2;
my $value = $3;
if ( $operator eq 'true' and $hash{$value} ) {
$replacement = qq{<if state1="yes"/>};
}
elsif ( $operator eq 'false' and not $hash{$value} ) {
$replacement = qq{<if state1="no"/>};
}
$replacement;
}eg;
Upvotes: 4
Reputation: 1810
$var=$ARGV[0];
my %hash =(
a => 1,
b => 2
);
while ( $var =~ /<IF OPERATOR="(.+?)" VALUE="(.+?)"\/>/ ) {
my $operator = $1;
my $value = $2;
if ( $operator eq 'true' && $hash{ $value } ) {
$var =~ s/<IF OPERATOR="$operator" VALUE="$value"\/>/ReplacemenT/g;
}
if ( $operator eq 'false' && ! $hash{ $value } ) {
$var =~ s/<IF OPERATOR="$operator" VALUE="$value"\/>/RR/g;
}
}
print "$var\n";
on something like 'xxx<IF OPERATOR="true" VALUE="a"/>xxx'
returns xxxReplacemenTxxx
Upvotes: -2
Reputation: 151916
A lot of logic can be placed in regular expressions. For instance, there are conditional regular expressions, and you can execute Perl code in a regexp.
If you don't want to complicate the regexp, you can extract the offsets of the matches first, then splice them out with substr EXPR, OFFSET, LENGTH, ''
.
But for the fun of using regexps, with named backreferences and s///e (evaluate the replacement), here is the code:
#!/usr/bin/perl -w
use strict;
my %hash = (
foo => 1,
bar => 0
);
my $var = '
<IF OPERATOR="true" VALUE="foo"/>
<IF OPERATOR="true" VALUE="bar"/>
<IF OPERATOR="false" VALUE="foo"/>
<IF OPERATOR="false" VALUE="bar"/>
';
$var =~
s`(<IF\s+OPERATOR="(?<operator>.+?)"\s+VALUE="(?<value>.+?)"/>)
`$+{operator} eq 'true' && $hash{ $+{value} } || $+{operator} eq 'false' && !$hash{ $+{value} }? 'replacement' : $1
`xeg;
print $var;
Upvotes: 1