perl bug with pos() and placing matches in an array?

Discussion in 'Perl Misc' started by t13_e@yahoo.com, Mar 16, 2005.

  1. Guest

    For this code:

    $x1 = "abcdefgh";

    if(@vars = ($x1 =~ m/(b)/g))
    {
    $p = pos $x1;
    print "pos is $p\n";
    }

    $x2 = "abcdefgh";

    if($x2 =~ m/(b)/g)
    {
    $p = pos $x2;
    print "pos is $p\n";
    }

    The following is displayed using perl v5.8.4:

    pos is
    pos is 2


    Does someone know why pos is returning '' for the first regexp, and the
    correct value, 2, for the second?

    Thanks,

    Tim
    , Mar 16, 2005
    #1
    1. Advertising

  2. wrote in news:1111011457.955716.49950
    @f14g2000cwb.googlegroups.com:

    Subject: perl bug with pos() and placing matches in an array?

    As I have pointed out many times before, it never fails to astonish me
    when people automatically assume there is a "bug" as opposed to
    realizing that they may be missing something.

    > For this code:
    >
    > $x1 = "abcdefgh";
    >
    > if(@vars = ($x1 =~ m/(b)/g))
    > {
    > $p = pos $x1;
    > print "pos is $p\n";
    > }


    See perldoc perlop:

    m/PATTERN/cgimosx
    /PATTERN/cgimosx
    ....
    Options are:
    c Do not reset search position on a failed match when /g is
    in effect.

    ....

    The "/g" modifier specifies global pattern matching--that is,
    matching as many times as possible within the string.

    Hence, by the time of the call to pos above, the match will have failed,
    and therefore the search position will have been reset (because you did
    not use the c option.

    D:\Home\asu1> cat v.pl

    use strict;
    use warnings;

    my $x1 = "abcdefgh";

    if(my @vars = ($x1 =~ m/(b)/cg)) {
    my $p = pos $x1;
    print "pos is $p\n";
    }

    my $x2 = "abcdefgh";

    if($x2 =~ m/(b)/g) {
    my $p = pos $x2;
    print "pos is $p\n";
    }
    __END__

    D:\Home\asu1> v
    pos is 2
    pos is 2

    You will become much better at programming if you first assume that you
    might, just might, be making a mistake instead of being convinced that
    there is a bug in something someone else did every time things don't
    work in line with your expectations.

    Sinan

    Sinan
    A. Sinan Unur, Mar 16, 2005
    #2
    1. Advertising

  3. Guest

    I see... sorry, I was assuming that "@vars = $x =~ m/(a)/" worked the
    same as "@vars = $x =~ m/(a)/g", except that the /g would enable me to
    get the position of the match.

    I'm trying to do a single match, place the submatches in an array, and
    at the same time finding the position of the match. I don't want to
    use $1,$2,$3, etc... since the regexp is dynamic and created at
    runtime. Do you have any idea of how to accomplish this without using
    "length &`"?

    Thanks,

    Tim
    , Mar 16, 2005
    #3
  4. wrote in news:1111017413.199762.176700
    @g14g2000cwa.googlegroups.com:

    > I see


    What do you see? Please quote an appropriate amount of context when
    replying.

    > ... sorry, I was assuming that "@vars = $x =~ m/(a)/" worked the
    > same as "@vars = $x =~ m/(a)/g", except that the /g would enable me to
    > get the position of the match.
    >
    > I'm trying to do a single match, place the submatches in an array, and
    > at the same time finding the position of the match.


    The position of which match? You can only hope to get the position of
    the *last* match using the c option.

    > I don't want to use $1,$2,$3, etc...


    Who said you needed to?

    If you want to get the position of all the matches in a string, then
    you'll need to loop trough the matches, saving the position of the match
    in each case.

    > Do you have any idea of how to accomplish this without using
    > "length &`"?


    What is &` ?

    I think, at this point, you need to take deep breath, read the posting
    guidelines to get some pointers on how to compose a meaningful post that
    helps others help you, and follow up with an accurate description of
    what you are trying to achieve.

    Sinan.
    A. Sinan Unur, Mar 17, 2005
    #4
  5. Guest

    A. Sinan Unur wrote:
    > wrote in news:1111017413.199762.176700
    > @g14g2000cwa.googlegroups.com:
    >
    > > I see

    >
    > What do you see? Please quote an appropriate amount of context when
    > replying.


    This is just an expression. I'll refrain from using these from now on.

    >
    > > ... sorry, I was assuming that "@vars = $x =~ m/(a)/" worked the
    > > same as "@vars = $x =~ m/(a)/g", except that the /g would enable me

    to
    > > get the position of the match.
    > >
    > > I'm trying to do a single match, place the submatches in an array,

    and
    > > at the same time finding the position of the match.

    >
    > The position of which match? You can only hope to get the position of


    > the *last* match using the c option.


    I would like to find the position of the first match.

    I'll try to describe this more plainly. I have a string, $x, that may
    match one or more times to a regexp, $re. $re is defined at runtime,
    and contains one or more groupings using '(' and ')'.

    I want to find the first match in the string, place all the submatches
    of the first match into an array, @vars. I also would like to find the
    position in $x of the first match.

    It seems like the answer is to attempt the match twice, as follows:

    $x = "abcdefg";

    $re = qr/([bd])(.)/;

    if(@vars = $x =~ /$re/) #get the submatches of the first match
    {
    $x =~ /$re/g; #find the position of the first match
    $p = pos($x) - length $&;
    print "pos is $p\n";
    print "vars = ".join(' ',@vars)."\n";
    }

    If know of a nicer, more efficient way of doing this, then great.
    Otherwise, thanks for your time.

    >
    > > I don't want to use $1,$2,$3, etc...

    >
    > Who said you needed to?
    >
    > If you want to get the position of all the matches in a string, then
    > you'll need to loop trough the matches, saving the position of the

    match
    > in each case.
    >
    > > Do you have any idea of how to accomplish this without using
    > > "length &`"?

    >
    > What is &` ?
    >


    Sorry, I meant "$`"...

    > I think, at this point, you need to take deep breath, read the

    posting
    > guidelines to get some pointers on how to compose a meaningful post

    that
    > helps others help you, and follow up with an accurate description of
    > what you are trying to achieve.
    >
    > Sinan.
    , Mar 17, 2005
    #5
  6. <> wrote:
    > For this code:
    >
    > $x1 = "abcdefgh";
    >
    > if(@vars = ($x1 =~ m/(b)/g))



    A pattern match in list context.

    It matches as many times as it can right here, then it is done matching.

    > {
    > $p = pos $x1;
    > print "pos is $p\n";
    > }
    >
    > $x2 = "abcdefgh";
    >
    > if($x2 =~ m/(b)/g)



    A pattern match in scalar context.

    Must remember pos() in case we resume matching against $x2.


    > {
    > $p = pos $x2;
    > print "pos is $p\n";
    > }
    >
    > The following is displayed using perl v5.8.4:
    >
    > pos is
    > pos is 2
    >
    >
    > Does someone know why pos is returning '' for the first regexp,



    Because it is all done matching before you get to calling pos().


    > and the
    > correct value, 2, for the second?



    Because it is still matching, so it is still maintaining position info.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Mar 17, 2005
    #6
  7. * wrote:
    >
    > I want to find the first match in the string, place all the submatches
    > of the first match into an array, @vars. I also would like to find the
    > position in $x of the first match.
    >
    > It seems like the answer is to attempt the match twice, as follows:
    >
    > $x = "abcdefg";
    > $re = qr/([bd])(.)/;
    >
    > if(@vars = $x =~ /$re/) #get the submatches of the first match
    > {
    > $x =~ /$re/g; #find the position of the first match
    > $p = pos($x) - length $&;
    > print "pos is $p\n";
    > print "vars = ".join(' ',@vars)."\n";
    > }


    Have a look at `perldoc perlvar` where you can learn more about Perl's
    predefined variables. The array @+ should contain the same value as what
    the pos function returns.

    if ( @vars = $x =~ /$re/ ) {
    $p = $+[0] - length $&;
    print "pos is $p\n";
    print "vars = @vars\n"; # special var $" is a blank per default
    }

    Since you want to know the offset of the start of your match, you could
    use the array @- instead of @+.

    if ( @vars = $x =~ /$re/ ) {
    print "pos is $-[0]\n";
    print "vars = @vars\n";
    }

    regards,
    fabian
    Fabian Pilkowski, Mar 17, 2005
    #7
    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. Alan Davies
    Replies:
    7
    Views:
    189
    Alan Davies
    Nov 27, 2003
  2. John W. Long

    perl pos function equivalent in ruby?

    John W. Long, Apr 8, 2004, in forum: Ruby
    Replies:
    4
    Views:
    167
    Robert Klemme
    Apr 13, 2004
  3. snacktime

    ruby equiv of perl pos

    snacktime, Aug 12, 2006, in forum: Ruby
    Replies:
    14
    Views:
    194
    Thomas, Mark - BLS CTR
    Aug 17, 2006
  4. andrey

    IO.pos bug?

    andrey, Jul 28, 2008, in forum: Ruby
    Replies:
    5
    Views:
    92
    Nobuyoshi Nakada
    Jul 31, 2008
  5. prati
    Replies:
    0
    Views:
    413
    prati
    Oct 27, 2012
Loading...

Share This Page