David
David

Reputation: 165

Computed regular expression replacement in Perl

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

Answers (3)

Borodin
Borodin

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

cur4so
cur4so

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

Dan Dascalescu
Dan Dascalescu

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

Related Questions