palkia has asked for the wisdom of the Perl Monks concerning the following question:

Hi everyone

I'm stuck on this for some time now so I'm really appreciate any help.
I ned to do a substitution based on a regex pattern given by the user.
I also need the substituting value to be dependent on the user's choice, (user say 1 -> I refer to $1, user say 2...).
(yes the user knows perl regex ^^)
If I knew how I would refer to some array containing $1,$2,$3... but I don't know of such array (do u?).
so I tried this
my temp4ev = '$'.$fromUserNumber; @simMatches = map{$_ =~ s/$pat/eval($temp4ev)/e} @simMatches;
but that didn't do the trick, nor any other variation of the var & eval.
it just turn everything to "1".

Thx

Update: Problem Resolved !

Replies are listed 'Best First'.
Re: Is there an array for $1,$2,$3... or some alternative ?
by davido (Cardinal) on Mar 14, 2012 at 03:52 UTC

    Evaluating a match operator in list context will return a list of the contents of the match's captures. Example:

    my $string = 'abcde'; my @captures = $string =~ m/.(.)(.)(.)./; print "$_\n" for @captures; __END__ b c d

    What I think you're attempting to construct is a symbolic reference named by user input. That's a bad idea, as the user could access any global variable in your program, intentionally or unintentionally. Just capture into an array as demonstrated above.


    Dave

      Don't worry, the user was only able to enter a positive integer (anything else if rejected ^^)
      Any way your solution worked gr8, thx.

      Looking back now, I should've know it returns a list of matches, considering I learned long ago (by experimenting), that it returns the number of matches (in scalar context),
      So I've earned myself some mto point ^^
      Thx again
Re: Is there an array for $1,$2,$3... or some alternative ?
by jwkrahn (Abbot) on Mar 14, 2012 at 04:49 UTC

    It looks like you need something like this:

    $ perl -le'my $fromUserNumber = shift; $_ = " a b c d "; /(.) (.) (.) +(.)/ and print substr $_, $-[$fromUserNumber], $+[$fromUserNumber] - +$-[$fromUserNumber]' 2 b $ perl -le'my $fromUserNumber = shift; $_ = " a b c d "; /(.) (.) (.) +(.)/ and print substr $_, $-[$fromUserNumber], $+[$fromUserNumber] - +$-[$fromUserNumber]' 3 c
Re: Is there an array for $1,$2,$3... or some alternative ?
by JavaFan (Canon) on Mar 14, 2012 at 07:37 UTC
    There isn't an array, but there are @- and @+ which store offsets. But I prefer to use symbolic references in this case. For instance, to get an array of all the matches1:
    my @matches = map {;no strict 'refs'; $$_} 1 .. $#-;

    1You can not always capture the return values of the match and get the same effect.

Re: Is there an array for $1,$2,$3... or some alternative ?
by Marshall (Canon) on Mar 14, 2012 at 03:59 UTC
    eval($temp4ev) is just going to report success or not (0,1)

    Can you give one clear example of how you want this to work?

    I would suggest writing some text explanation of what you think should happen.

      The user choses both the value of $fromUserNumber and of $pat
      when $fromUserNumber in a positive integer !
      I wanted that when $fromUserNumber == 1 the line will be
      @simMatches = map{$_ =~ s/$pat/$1/} @simMatches;
      when $fromUserNumber == 2 the line will be
      @simMatches = map{$_ =~ s/$pat/$2/} @simMatches; and so on.
        When you think of a subset of an array, think grep.
        Use map only when you think of transforming one thing into another.
        Perl variables can be interpolated into a regex expression.
        my $pat = "somepattern"; @simMatches = grep{/$pat$num/} @simMatches; # subset of @simMatches
        Show a couple of lines of actual data and this can all become clear.
        $1 or $2 are regex capture variables that don't seem to play a role here.
Re: Is there an array for $1,$2,$3... or some alternative ?
by Anonymous Monk on Mar 14, 2012 at 05:02 UTC
    chomp(my $input = <STDIN>); my @simMatches = qw(abcd wxyz); my $pat = qr/(.)..(.)/; @simMatches = map{ @_ = /$pat/; s/$pat/$_[$input-1]/; $_ }@simMatches; print join $", @simMatches; __END__ $input == 1; a w $input == 2; d z