For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > January 2006 > Reading the built-in number variables









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Reading the built-in number variables
vansyckellist@wowway.com

2006-01-10, 4:01 am

The issue:

I have a routine which builds a regex and 'knows' which paren matches to use
afterwords. For instance after a line such as:

use strict;
my $data =~ m/^(\S+)\s+((\S+\s+)?(\S+))$/;

the routine 'knows' it wants $1 and $4. Another pass through the regex will
be different and the variables might be $2 and $5 for that regex.

The needed variable numbers are in an array:
my @indexes;
@indexes = (1, 4); for the first example above and:
@indexes = (2, 5); for the second example above.

The question:
Is there a way to reference the built-in variables: $1, $2, ... in a
programmatic manner?

Something like:
@values;
push @values,${$_} foreach(@indexes);
which didn't work for me, but you get the idea.

Yes, I already thought of a subroutine with a big ifels ladder that hard codes
a test for $1, $2, ... but there has to be a more eloquent solution than this.

Thanks,
Don

John W. Krahn

2006-01-10, 4:01 am

vansyckellist@wowway.com wrote:
> The issue:
>
> I have a routine which builds a regex and 'knows' which paren matches to use
> afterwords. For instance after a line such as:
>
> use strict;
> my $data =~ m/^(\S+)\s+((\S+\s+)?(\S+))$/;
>
> the routine 'knows' it wants $1 and $4. Another pass through the regex will
> be different and the variables might be $2 and $5 for that regex.
>
> The needed variable numbers are in an array:
> my @indexes;
> @indexes = (1, 4); for the first example above and:
> @indexes = (2, 5); for the second example above.
>
> The question:
> Is there a way to reference the built-in variables: $1, $2, ... in a
> programmatic manner?
>
> Something like:
> @values;
> push @values,${$_} foreach(@indexes);
> which didn't work for me, but you get the idea.
>
> Yes, I already thought of a subroutine with a big ifels ladder that hard codes
> a test for $1, $2, ... but there has to be a more eloquent solution than this.


You may need to use the @- and @+ arrays, see:

perldoc perlvar

for an explanation.


John
--
use Perl;
program
fulfillment
usenet@DavidFilmer.com

2006-01-10, 4:01 am

vansyckellist@wowway.com wrote:
> Is there a way to reference the built-in variables: $1, $2, ... in a
> programmatic manner?


You can assign the results of your match to an array. When you wrote:

> my $data =~ m/^(\S+)\s+((\S+\s+)?(\S+))$/;


I think you really wanted to do something like this (assuming you're
matching against $_):

my @data = (m/^(\S+)\s+((\S+\s+)?(\S+))$/);

in which case, $data[0] eq $1, $data[1] eq $2, etc. You can take a
slice of the array if you wish, such as $data[0,2] - same as ($1, $3)

Bob Showalter

2006-01-10, 4:01 am

vansyckellist@wowway.com wrote:
> The issue:
>
> I have a routine which builds a regex and 'knows' which paren matches to use
> afterwords. For instance after a line such as:
>
> use strict;
> my $data =~ m/^(\S+)\s+((\S+\s+)?(\S+))$/;
>
> the routine 'knows' it wants $1 and $4. Another pass through the regex will
> be different and the variables might be $2 and $5 for that regex.
>
> The needed variable numbers are in an array:
> my @indexes;
> @indexes = (1, 4); for the first example above and:
> @indexes = (2, 5); for the second example above.
>
> The question:
> Is there a way to reference the built-in variables: $1, $2, ... in a
> programmatic manner?
>
> Something like:
> @values;
> push @values,${$_} foreach(@indexes);
> which didn't work for me, but you get the idea.


That should work if @indexes contains numbers like

@indexes = (1, 3);

You'll also need to disable strict refs:

no strict 'refs';

However, another approach would be to do your regex match in list
context, and place the captured substrings into an array that you can index:

my @fields = $data =~ m/^(\S+)\s+((\S+\s+)?(\S+))$/;
@values = @fields[@indexes];

Here the first match is at index 0 (i.e. $1 is @values[0])

>
> Yes, I already thought of a subroutine with a big ifels ladder that hard codes
> a test for $1, $2, ... but there has to be a more eloquent solution than this.
>
> Thanks,
> Don
>
>


Don VanSyckel

2006-01-10, 4:02 am

The approach of using list context for the match and the array slice:
my @fields = $data =~ m/^(\S+)\s+((\S+\s+)?(\S+))$/;
@values = @fields[@indexes];

is exactly what I needed.

I still can't find this referenced in the docs though.

Thanks,
Don


On Tuesday 20 December 2005 09:30, Bob Showalter wrote:[color=darkred]
> vansyckellist@wowway.com wrote:
>
> That should work if @indexes contains numbers like
>
> @indexes = (1, 3);
>
> You'll also need to disable strict refs:
>
> no strict 'refs';
>
> However, another approach would be to do your regex match in list
> context, and place the captured substrings into an array that you can
> index:
>
> my @fields = $data =~ m/^(\S+)\s+((\S+\s+)?(\S+))$/;
> @values = @fields[@indexes];
>
> Here the first match is at index 0 (i.e. $1 is @values[0])
>

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com