Using match variables ($1, $2 ...) as variables.

R

Ravi Parimi

Hi,
I have a string that gets generated on the fly. Based on the
number of times a particular word appears in this string, I generate my
matching pattern. As an example..

$string = "<Data><Size>12</Size>one string<Size>100</Size>Another
string</Data>";

Now, based on the number of <Size> tags in the string, I create a regular
expression such as

my $count = $string =~ s#<Size>##gs;
my $str = "";
for ($i = 1;$i <= $count;++$count) {
$str .= "<Size>(\\d+)</Size>(.*)";
}

And now I wish to extract all odd-numbered match variables from the
matching($1, $3, $5 etc..)

$string =~ /$str/; # Match always succeeds as I know what's in $string

In a for loop, I wish to check if each of the $1,$2,$3...variables are
defined, and am not quite sure how to do that.


Usage of ${$i} is incorrect and doesnt make sense. Can someone suggest a
method by which I can find out if $1, $2, $3 ..are defined?


As an alternative, I have tried XML Parser to parse the above string but
had no luck with it.. Any help is appreciated.

Thanks,
--ravi
 
B

Bob Walton

Ravi Parimi wrote:

....
I have a string that gets generated on the fly. Based on the
number of times a particular word appears in this string, I generate my
matching pattern. As an example..

$string = "<Data><Size>12</Size>one string<Size>100</Size>Another
string</Data>";

Now, based on the number of <Size> tags in the string, I create a regular
expression such as

my $count = $string =~ s#<Size>##gs;


Why do you have the "s" modifier on this regexp? You don't use the .
metacharacter in it, and the "s" modifiers only purpose is to change the
behavior of the . metacharacter.

my $str = "";
for ($i = 1;$i <= $count;++$count) {


Hmmmmm...if $count is, for example, 3, then this will loop forever
(well, until overflow, anyway), as $i will remain 1 and count will
increment to 4, 5, 6, etc. What is your real code?

$str .= "<Size>(\\d+)</Size>(.*)";
}

And now I wish to extract all odd-numbered match variables from the
matching($1, $3, $5 etc..)

$string =~ /$str/; # Match always succeeds as I know what's in $string

In a for loop, I wish to check if each of the $1,$2,$3...variables are
defined, and am not quite sure how to do that.


Usage of ${$i} is incorrect and doesnt make sense. Can someone suggest a
method by which I can find out if $1, $2, $3 ..are defined?


Check out:

perldoc perlvar

in particular the part where it talks about the @- and @+ variables.
These give you programmatic access to the $1, $2, etc variables, via
substr() and the variable you matched the pattern against.
 
T

Tassilo v. Parseval

Also sprach Ravi Parimi:
I have a string that gets generated on the fly. Based on the
number of times a particular word appears in this string, I generate my
matching pattern. As an example..

$string = "<Data><Size>12</Size>one string<Size>100</Size>Another
string</Data>";

Now, based on the number of <Size> tags in the string, I create a regular
expression such as

my $count = $string =~ s#<Size>##gs;
my $str = "";
for ($i = 1;$i <= $count;++$count) {
$str .= "<Size>(\\d+)</Size>(.*)";
}

And now I wish to extract all odd-numbered match variables from the
matching($1, $3, $5 etc..)

$string =~ /$str/; # Match always succeeds as I know what's in $string

In a for loop, I wish to check if each of the $1,$2,$3...variables are
defined, and am not quite sure how to do that.

A more natural solution would be changing the pattern accordingly. You
always add two pairs of capturing parens. What is the second pair for?

Other than that, do the pattern match in list context and extract the
uneven elements from the array:

my @matches = $string =~ /$str/;
@matches = map { $_ % 2 ? $matches[$_] : () } 0 .. $#matches;

Tassilo
 
G

gnari

Tassilo v. Parseval said:
Also sprach Ravi Parimi:
my @matches = $string =~ /$str/;
@matches = map { $_ % 2 ? $matches[$_] : () } 0 .. $#matches;

exept that the greedy (.*) will spoin the match it there are more that
2 pairs of the tags.

I would skip the pattern building and just do (untested):
my @matches = $string =~ /<Size>(\d+)</Size>([^<]*)/gs;
and then process the array similarly to Tassilo.

gnari
 
T

Tad McClellan

gnari said:
my @matches = $string =~ /<Size>(\d+)</Size>([^<]*)/gs;


m//s only affects dot.

You never need a m//s when there is no dot in the pattern.
 
G

GreenLight

Ravi Parimi said:
Hi,
I have a string that gets generated on the fly. Based on the
number of times a particular word appears in this string, I generate my
matching pattern. As an example..

$string = "<Data><Size>12</Size>one string<Size>100</Size>Another
string</Data>";

Now, based on the number of <Size> tags in the string, I create a regular
expression such as

my $count = $string =~ s#<Size>##gs;
my $str = "";
for ($i = 1;$i <= $count;++$count) {
$str .= "<Size>(\\d+)</Size>(.*)";
}

And now I wish to extract all odd-numbered match variables from the
matching($1, $3, $5 etc..)

$string =~ /$str/; # Match always succeeds as I know what's in $string

In a for loop, I wish to check if each of the $1,$2,$3...variables are
defined, and am not quite sure how to do that.


Usage of ${$i} is incorrect and doesnt make sense. Can someone suggest a
method by which I can find out if $1, $2, $3 ..are defined?


As an alternative, I have tried XML Parser to parse the above string but
had no luck with it.. Any help is appreciated.

Thanks,
--ravi

Perhaps you are trying to overcomplicate the solution. Look at this:

my $string = "<Data><Size>12</Size>one string<Size>100</Size>Another
string</Data>"; # <-- this string should not be wrapped
my @rows = ($string =~ /<Size>(\d+)<\/Size>/gi);
foreach (@rows) {
print "$_\n";
}

That snippet of code produces this:
12
100

When you capture the result of the pattern match ("my @rows =...") in
list context, you get all of the matches as a list.

Is that what you want to accomplish?
 
G

gnari

Tad McClellan said:
gnari said:
my @matches = $string =~ /<Size>(\d+)</Size>([^<]*)/gs;


m//s only affects dot.

You never need a m//s when there is no dot in the pattern.

yep. had started with (.*), and changed it to ([^<]*) ,but
forgot to take the /s out.
 
U

Uri Guttman

g> "Tad McClellan said:
gnari said:
my @matches = $string =~ /<Size>(\d+)</Size>([^<]*)/gs;


m//s only affects dot.

You never need a m//s when there is no dot in the pattern.

g> yep. had started with (.*), and changed it to ([^<]*) ,but
g> forgot to take the /s out.

i have been there and done that. :)

that is a useful regex transform to know. mastering regular expressions
covers it well.

uri
 
R

Ravi Parimi

Hi,
Perhaps you are trying to overcomplicate the solution. Look at this:

my $string = "<Data><Size>12</Size>one string<Size>100</Size>Another
string</Data>"; # <-- this string should not be wrapped
my @rows = ($string =~ /<Size>(\d+)<\/Size>/gi);
foreach (@rows) {
print "$_\n";
}

That snippet of code produces this:
12
100

When you capture the result of the pattern match ("my @rows =...") in
list context, you get all of the matches as a list.

Is that what you want to accomplish?

This was what I was exactly looking for. It looks a lot more less
complicated than what the other posters suggested. Thanks a lot for your
help :)

--ravi
 
R

Ravi Parimi

...
Why do you have the "s" modifier on this regexp? You don't use the .
metacharacter in it, and the "s" modifiers only purpose is to change the
behavior of the . metacharacter.


It was a typo. I should've posted my complete code rather than typing
snippets here and there..
Check out:

perldoc perlvar

in particular the part where it talks about the @- and @+ variables.
These give you programmatic access to the $1, $2, etc variables, via
substr() and the variable you matched the pattern against.

Thanks for the pointer to perlvar. I didnt know that @-,@+ existed prior
to reading this.

--ravi
 
R

Ravi Parimi

I have a string that gets generated on the fly. Based on the
number of times a particular word appears in this string, I generate my
matching pattern. As an example..

$string = "<Data><Size>12</Size>one string<Size>100</Size>Another
string</Data>";

Now, based on the number of <Size> tags in the string, I create a regular
expression such as

my $count = $string =~ s#<Size>##gs;
my $str = "";
for ($i = 1;$i <= $count;++$count) {
$str .= "<Size>(\\d+)</Size>(.*)";
}

And now I wish to extract all odd-numbered match variables from the
matching($1, $3, $5 etc..)

$string =~ /$str/; # Match always succeeds as I know what's in $string

In a for loop, I wish to check if each of the $1,$2,$3...variables are
defined, and am not quite sure how to do that.

A more natural solution would be changing the pattern accordingly. You
always add two pairs of capturing parens. What is the second pair for?

Other than that, do the pattern match in list context and extract the
uneven elements from the array:

my @matches = $string =~ /$str/;
@matches = map { $_ % 2 ? $matches[$_] : () } 0 .. $#matches;

You solution also worked for me prefectly. Thanks a lot for your reply!
I took care of the greedy matching problem as suggested by Gnari and Tad.

--ravi
 
T

Tad McClellan

Ravi Parimi said:
I should've posted my complete code rather than typing
snippets here and there..


Have you seen the Posting Guidelines that are posted here frequently?
 
T

Tad McClellan

[ snip 50-line full-quote with no attribution.
Please learn how to properly compose a followup.
Please do this soon.
]

This was what I was exactly looking for. It looks a lot more less
^^^^ ^^^^
^^^^ ^^^^
complicated than what the other posters suggested.


Huh?
 
K

Kevin Collins

[A complimentary Cc of this posting was sent to
Ravi Parimi
Usage of ${$i} is incorrect and doesnt make sense.

Could you elaborate on this point?
perl -wle "'abcde' =~ /(.)c(.)/ or die; $v=2; print $$v"
d

And ${$v} is another way of writing $$v... see 'perldoc perlref', specifically
item #2 under section "Using References".

Kevin
 
T

Thomas Kratz

Kevin said:
[A complimentary Cc of this posting was sent to
Ravi Parimi
Usage of ${$i} is incorrect and doesnt make sense.

Could you elaborate on this point?
perl -wle "'abcde' =~ /(.)c(.)/ or die; $v=2; print $$v"
d


And ${$v} is another way of writing $$v... see 'perldoc perlref', specifically
item #2 under section "Using References".

You are missing the point. Ilya just wanted to know how the usage of ${$i}
is incorrect or doesn't make sense. And he provided a syntactically
correct example, that does make some sense (for arbitrary values of sense).

Thomas
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top