Help: Nested quantifiers in regex Problem

Discussion in 'Perl Misc' started by Amy Lee, Oct 24, 2008.

  1. Amy Lee

    Amy Lee Guest

    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
     
    Amy Lee, Oct 24, 2008
    #1
    1. Advertising

  2. Amy Lee wrote:
    >
    > 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
    --
    Perl isn't a toolbox, but a small machine shop where you
    can special-order certain sorts of tools at low cost and
    in short order. -- Larry Wall
     
    John W. Krahn, Oct 24, 2008
    #2
    1. Advertising

  3. On Fri, 24 Oct 2008 12:50:23 +0800,
    Amy Lee <> wrote:
    > 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
    --
    |
    Martien Verbruggen | Quick! Hire a teenager while they still know
    | everything.
    |
     
    Martien Verbruggen, Oct 24, 2008
    #3
  4. Amy Lee

    Amy Lee Guest

    On Fri, 24 Oct 2008 17:51:14 +1100, Martien Verbruggen wrote:

    > On Fri, 24 Oct 2008 12:50:23 +0800,
    > Amy Lee <> wrote:
    >> 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

    Thank you guys, I use \Q to solve that. Really thank you very much.
     
    Amy Lee, Oct 24, 2008
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    1
    Views:
    399
    Joshua Cranmer
    Sep 9, 2007
  2. NeoGeoSNK
    Replies:
    4
    Views:
    3,738
    Joshua Cranmer
    Mar 3, 2008
  3. Nathan Sokalski

    JavaScript RegExp Quantifiers

    Nathan Sokalski, Jun 11, 2008, in forum: ASP .Net
    Replies:
    2
    Views:
    372
    Hans Kesting
    Jun 13, 2008
  4. Wolfgang Thomas
    Replies:
    16
    Views:
    230
    Xicheng
    Mar 9, 2006
  5. Replies:
    0
    Views:
    152
Loading...

Share This Page