1

I'm aware of the match, prematch, and postmatch predefined variables. I'm wondering if there is something similar for the evaluated replacement part of the s/// operator.

This would be particularly useful in dynamic expressions so they don't have to be evaluated a 2nd time.

For example, I currently have %regexs which is a hash of various search and replace strings.

Here's a snippet:

while (<>) {
  foreach my $key (keys %regexs) {   
    while (s/$regexs{$key}{'search'}/$regexs{$key}{'replace'}/ee) { 
      # Here I want to do something with just the replaced part 
      # without reevaluating.
    } 
  }
  print;
}

Is there a convenient way to do it? Perl seems to have so many convenient shortcuts, and it seems like a waste to have to evaluate twice (which appears to be the alternative).

EDIT: I just wanted to give an example: $regexs{$key}{'replace'} might be the string '"$2$1"' thus swapping the positions of some text in the string $regexs{$key}{'search'} which might be '(foo)(bar)' - thus resulting in "barfoo". The second evaluation that I'm trying to avoid is the output of $regexs{$key}{'replace'}.

4 Answers 4

2

Instead of using string eval (which I assume is what's going on with s///ee), you could define code references to do the work. Those code references can then return the value of the replacement text. For example:

use strict;
use warnings;

my %regex = (
    digits  => sub {
        my $r;
        return unless $_[0] =~ s/(\d)(\d)_/$r = $2.$1/e;
        return $r;
    },
);

while (<DATA>){
    for my $k (keys %regex){
        while ( my $replacement_text = $regex{$k}->($_) ){
            print $replacement_text, "\n";
        }
    }
    print;
}

__END__
12_ab_78_gh_
34_cd_78_yz_
Sign up to request clarification or add additional context in comments.

Comments

1

I'm pretty sure there isn't any direct way to do what you're asking, but that doesn't mean it's impossible. How about this?

{
  my $capture;
  sub capture {
    $capture = $_[0] if @_;
    $capture;
  }
}

while (s<$regexes{$key}{search}>
        <"capture('" . $regexes{$key}{replace}) . "')">eeg) {
  my $replacement = capture();
  #...
}

Well, except to do it really properly you'd have to shoehorn a little more code in there to make the value in the hash safe inside a singlequotish string (backslash singlequotes and backslashes).

Comments

1

If you do the second eval manually you can store the result yourself.

my $store;
s{$search}{ $store = eval $replace }e;

2 Comments

The last $store is redundant, though; assignment returns the value assigned.
Ahh, true. Also its redundant.
0

why not assign to local vars before:

my $replace = $regexs{$key}{'replace'};

now your evaluating once.

1 Comment

Thx, but my question may have been unclear. I'm using the /ee modifier to evaluate what $regexs{$key}{'replace'} evaluates to, which may be dependent on $regexs{$key}{'search'}.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.