Help: Nested quantifiers in regex Problem

A

Amy Lee

Hello,

I use qw to make a list with
my @sample = qw/"A..." "A..+" "A.+." "A+.." "A.++" "A+.+" "A++." "A+++"/;
Then there's a list called @ar and I want check whether the element at
@sample belongs to @ar. So I wrote the following codes
foreach my $item_sample (@sample)
{
unless (grep /$item_sample/, @ar) #line 38
{
push @ar, "$item_sample";
}
}
But wehn I run my script it shows following error messages
Nested quantifiers in regex; marked by <-- HERE in m/"A.++ <-- HERE "/ at ./x.pl line 38, <> line 44.

So I really feel very confused about it. Could you tell me why it happens
and how can I fix that?

Thank you very much.

Amy
 
J

John W. Krahn

Amy said:
I use qw to make a list with
my @sample = qw/"A..." "A..+" "A.+." "A+.." "A.++" "A+.+" "A++." "A+++"/;
Then there's a list called @ar and I want check whether the element at
@sample belongs to @ar. So I wrote the following codes
foreach my $item_sample (@sample)
{
unless (grep /$item_sample/, @ar) #line 38
{
push @ar, "$item_sample";
}
}
But wehn I run my script it shows following error messages
Nested quantifiers in regex; marked by <-- HERE in m/"A.++ <-- HERE "/ at ./x.pl line 38, <> line 44.

So I really feel very confused about it. Could you tell me why it happens
and how can I fix that?

In a regular expression . matches any character except newline and .+
means to match any character one or more times. Trying to use .++ makes
no sense as you can't modify a modifier with +, only with ? so .+? would
be valid.




John
 
M

Martien Verbruggen

Hello,

I use qw to make a list with
my @sample = qw/"A..." "A..+" "A.+." "A+.." "A.++" "A+.+" "A++." "A+++"/;
Then there's a list called @ar and I want check whether the element at
@sample belongs to @ar. So I wrote the following codes
foreach my $item_sample (@sample)
{
unless (grep /$item_sample/, @ar) #line 38
{
push @ar, "$item_sample";
}
}
But wehn I run my script it shows following error messages
Nested quantifiers in regex; marked by <-- HERE in m/"A.++ <-- HERE "/
at ./x.pl line 38, <> line 44.

So I really feel very confused about it. Could you tell me why it happens
and how can I fix that?

In the above $item_sample is being treated as a regular expression. A
few of the things in @sample are simply not valid regular expressions. I
am assuming that you actually didn't mean them to be regular
expressions and that you wanted to check for string equality.

Also, are you aware that the strings you're looking at have double
quotes in them as well? Did you mean them to have those quotes in them?

There are a few ways in which you can fix this.

The minimal change is to correctly quote any metacharacters in the
regular expression (see the perlre documentation)

Change one line (your line 38):

unless (grep /\Q$item_sample/, @ar) #line 38

This does, however, probably not the right thing. It checks whether
$item_sample is PART of one of the elements of @ar. If you had "A+++"
and "A++" in that order in @sample, the second element would not end up
in @ar. I doubt that that was intentional.

You could anchor the regex at the start and end, but it would probably
be better to simply say what (I think) you mean, and test for equality:

unless (grep {$_ eq $item_sample} @ar) #line 38

This still is rather inefficient, because you have to loop through the
whole of @ar for every element of @sample. For small arrays that makes
no difference, but for larger arrays that is a problem.

I think that what you're trying to do is to assign the unique elements
of @sample to @ar, right? The canonical way to do that in Perl is by
using a hash:

my %seen;
my @ar = grep { ! $seen{$_}++ } @sample;

(Note that grep is used here only ones. These two lines are meant to
replace all the code you quoted above, not just line 38.)

Also check out the perlFAQ entry in perlfaq4 with the title "How can I
remove duplicate elements from a list or array?" This entry also
descibes this method with an explicit loop, instead of grep, which you
might find easier.

Martien
 
A

Amy Lee

In the above $item_sample is being treated as a regular expression. A
few of the things in @sample are simply not valid regular expressions. I
am assuming that you actually didn't mean them to be regular
expressions and that you wanted to check for string equality.

Also, are you aware that the strings you're looking at have double
quotes in them as well? Did you mean them to have those quotes in them?

There are a few ways in which you can fix this.

The minimal change is to correctly quote any metacharacters in the
regular expression (see the perlre documentation)

Change one line (your line 38):

unless (grep /\Q$item_sample/, @ar) #line 38

This does, however, probably not the right thing. It checks whether
$item_sample is PART of one of the elements of @ar. If you had "A+++"
and "A++" in that order in @sample, the second element would not end up
in @ar. I doubt that that was intentional.

You could anchor the regex at the start and end, but it would probably
be better to simply say what (I think) you mean, and test for equality:

unless (grep {$_ eq $item_sample} @ar) #line 38

This still is rather inefficient, because you have to loop through the
whole of @ar for every element of @sample. For small arrays that makes
no difference, but for larger arrays that is a problem.

I think that what you're trying to do is to assign the unique elements
of @sample to @ar, right? The canonical way to do that in Perl is by
using a hash:

my %seen;
my @ar = grep { ! $seen{$_}++ } @sample;

(Note that grep is used here only ones. These two lines are meant to
replace all the code you quoted above, not just line 38.)

Also check out the perlFAQ entry in perlfaq4 with the title "How can I
remove duplicate elements from a list or array?" This entry also
descibes this method with an explicit loop, instead of grep, which you
might find easier.

Martien
Thank you guys, I use \Q to solve that. Really thank you very much.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top