conditional regular expressions

Discussion in 'Perl Misc' started by Morfys, Aug 13, 2007.

  1. Morfys

    Morfys Guest

    hi,

    I was having trouble understanding how regular conditional expressions
    work. In particular, in this piece of code:

    $str = "ttt, 2";

    if(($result) = $str =~ /\w\w\w(?(?=, )(\d))/){

    print "$result\n";

    }

    I don't understand why there is empty output versus "2".

    The desired effect is that $result contain the digit following ", " if
    it exists in the string.

    I've tried almost every variation of the regular expression but I'm
    missing something. Thanks in advance for any help.
    Morfys, Aug 13, 2007
    #1
    1. Advertising

  2. Morfys

    Mirco Wahab Guest

    Morfys wrote:
    > $str = "ttt, 2";
    > if(($result) = $str =~ /\w\w\w(?(?=, )(\d))/){
    > print "$result\n";
    > }
    > I don't understand why there is empty output versus "2".
    > The desired effect is that $result contain the digit following ", " if
    > it exists in the string.


    The regular expression is stepped through from
    left to right. Therefore there is an implicit
    "the more right pattern matches only if the more
    left pattern already matched", which leads to the
    trivial solution 1.:

    my $str = 'ttt, 2';
    my $result;

    # trivial solution w/capturing
    ($result) = $str=~/\w{3}, (\d)/ and print "1. $result\n";

    If you want to do some more fancy stuff, you
    could 'ifify' the whole expression with
    a "positive lookbehind", like:

    # lookbehind (?<= ...), no capturing, /g in list context
    ($result) = $str=~/(?<=\w{3}, )\d/g and print "2. $result\n";

    Regards

    M.
    Mirco Wahab, Aug 13, 2007
    #2
    1. Advertising

  3. Morfys

    Guest

    Morfys <> wrote:
    > hi,
    >
    > I was having trouble understanding how regular conditional expressions
    > work. In particular, in this piece of code:
    >
    > $str = "ttt, 2";
    >
    > if(($result) = $str =~ /\w\w\w(?(?=, )(\d))/){
    >
    > print "$result\n";
    >
    > }
    >
    > I don't understand why there is empty output versus "2".


    ?= is zero-width, meaning that after the ', ' matches, the \d is left
    to match starting at the same place, namely, at the ','. Since ',' is not
    a \d, it can't match.

    >
    > The desired effect is that $result contain the digit following ", " if
    > it exists in the string.


    Isn't that just what the simple /\w\w\w, (\d)/ would do?

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Aug 13, 2007
    #3
  4. Morfys

    Morfys Guest

    Thanks a lot! Indeed my problem was that ?= is zero-width.

    > > The desired effect is that $result contain the digit following ", " if
    > > it exists in the string.

    >
    > Isn't that just what the simple /\w\w\w, (\d)/ would do?


    In fact, the example I gave was just to simplify things so that my
    question could be clear. In my "real" regular expression, I need to
    parse strings like
    "open(X,X)"
    and
    "open(X,X,X)"
    and so the conditional seems necessary.
    Morfys, Aug 14, 2007
    #4
  5. Morfys <> wrote:

    >> > The desired effect is that $result contain the digit following ", " if
    >> > it exists in the string.

    >>
    >> Isn't that just what the simple /\w\w\w, (\d)/ would do?

    >
    > In fact, the example I gave was just to simplify things so that my
    > question could be clear. In my "real" regular expression, I need to
    > parse strings like
    > "open(X,X)"
    > and
    > "open(X,X,X)"



    $_ = 'open(X,Y,Z)';
    my @parts = /(\w+)(?=[,)])/g;


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad McClellan, Aug 14, 2007
    #5
  6. Morfys wrote:
    > In fact, the example I gave was just to simplify things so that my
    > question could be clear.


    Then you didn't succeed very well. :)

    > In my "real" regular expression, I need to parse strings like
    > "open(X,X)"
    > and
    > "open(X,X,X)"
    > and so the conditional seems necessary.


    my $str = 'open(4,5,6)';
    if ( my ($digits) = $str =~ /open\((\d(?:,\d)*)\)/ ) {
    my @result = split /,/, $digits;
    print "@result\n";
    }

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Aug 14, 2007
    #6
  7. Morfys

    Mirco Wahab Guest

    Morfys wrote:
    > In fact, the example I gave was just to simplify things so that my
    > question could be clear. In my "real" regular expression, I need to
    > parse strings like
    > "open(X,X)"
    > and
    > "open(X,X,X)"
    > and so the conditional seems necessary.


    .... condition to branch on what?

    I could understand this intend
    to match a string like

    "open(X,X,X), 3"
    or
    "open(X,X), 2"

    but your example doesn't provide
    an ample motivation for introducting
    conditionals.

    Regards

    M.
    Mirco Wahab, Aug 14, 2007
    #7
  8. Morfys

    Mirco Wahab Guest

    Tad McClellan wrote:
    > Morfys <> wrote:
    >> "open(X,X)"
    >> and
    >> "open(X,X,X)"

    > $_ = 'open(X,Y,Z)';
    > my @parts = /(\w+)(?=[,)])/g;


    Just out of couriosity, what's the
    purpose of these fancy parenthesis
    around \w+ ? Is there any hidden
    mechanics to use them this way?

    Regards

    M.
    Mirco Wahab, Aug 14, 2007
    #8
  9. Tad McClellan wrote:
    > Morfys <> wrote:
    >> I need to parse strings like
    >> "open(X,X)"
    >> and
    >> "open(X,X,X)"

    >
    > $_ = 'open(X,Y,Z)';
    > my @parts = /(\w+)(?=[,)])/g;


    You don't need both capturing parentheses and the "(?= ... )" part, do you?

    my @parts = /(\w+)[,)]/g;

    or

    my @parts = /\w+(?=[,)])/g;

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Aug 14, 2007
    #9
  10. Morfys

    -berlin.de Guest

    Mirco Wahab <-halle.de> wrote in comp.lang.perl.misc:
    > Tad McClellan wrote:
    > > Morfys <> wrote:
    > >> "open(X,X)"
    > >> and
    > >> "open(X,X,X)"

    > > $_ = 'open(X,Y,Z)';
    > > my @parts = /(\w+)(?=[,)])/g;

    >
    > Just out of couriosity, what's the
    > purpose of these fancy parenthesis
    > around \w+ ? Is there any hidden
    > mechanics to use them this way?


    Hmm? What's fancy about them. They're normal capturing parentheses.

    Anno
    -berlin.de, Aug 14, 2007
    #10
  11. Morfys

    Mirco Wahab Guest

    -berlin.de wrote:
    > Mirco Wahab <-halle.de> wrote in comp.lang.perl.misc:
    >> Tad McClellan wrote:
    >>> Morfys <> wrote:
    >>>> "open(X,X)"
    >>>> and
    >>>> "open(X,X,X)"
    >>> $_ = 'open(X,Y,Z)';
    >>> my @parts = /(\w+)(?=[,)])/g;

    >> Just out of couriosity, what's the
    >> purpose of these fancy parenthesis
    >> around \w+ ? Is there any hidden
    >> mechanics to use them this way?

    >
    > Hmm? What's fancy about them. They're normal capturing parentheses.


    I wouldn't consider normal in the said example,
    therefore my question: "does the perl regex
    engine distinguish internal" between

    my @foo = /\w+(?= bar)/g;
    and
    my @foo = /(\w+)(?= bar)/g;

    I can't answer this for myself,
    thats the reason I asked Tad.

    Regards

    M.
    Mirco Wahab, Aug 14, 2007
    #11
  12. Morfys

    -berlin.de Guest

    Mirco Wahab <-halle.de> wrote in comp.lang.perl.misc:
    > -berlin.de wrote:
    > > Mirco Wahab <-halle.de> wrote in comp.lang.perl.misc:
    > >> Tad McClellan wrote:
    > >>> Morfys <> wrote:
    > >>>> "open(X,X)"
    > >>>> and
    > >>>> "open(X,X,X)"
    > >>> $_ = 'open(X,Y,Z)';
    > >>> my @parts = /(\w+)(?=[,)])/g;
    > >> Just out of couriosity, what's the
    > >> purpose of these fancy parenthesis
    > >> around \w+ ? Is there any hidden
    > >> mechanics to use them this way?

    > >
    > > Hmm? What's fancy about them. They're normal capturing parentheses.

    >
    > I wouldn't consider normal in the said example,


    I'm still not sure *why* you'd consider them abnormal. It's true that
    /g makes them redundant, but they function as they always do.

    > therefore my question: "does the perl regex
    > engine distinguish internal" between
    >
    > my @foo = /\w+(?= bar)/g;
    > and
    > my @foo = /(\w+)(?= bar)/g;
    >
    > I can't answer this for myself,
    > thats the reason I asked Tad.


    I can't speak for Tad, but the parens make the capture more robust
    while you change parts of the regex around.

    Anno
    -berlin.de, Aug 14, 2007
    #12
  13. Morfys

    Morfys Guest

    > I could understand this intended
    > to match a string like
    >
    > "open(X,X,X), 3"
    > or
    > "open(X,X), 2"


    that's what I meant. ;)
    Morfys, Aug 14, 2007
    #13
  14. Morfys

    Mirco Wahab Guest

    Morfys wrote:
    >> I could understand this intended
    >> to match a string like
    >>
    >> "open(X,X,X), 3"
    >> or
    >> "open(X,X), 2"

    >
    > that's what I meant. ;)


    OK, then there are some solutions available,
    my first trial would be something like:

    ....
    my @strings = (
    "open(X,X,X), 1",
    "open(X,X,X), 3",
    "open(X,X,X), 31",
    "open(X,X), 2",
    "open(X,X), 23",
    "open(X,X), 32" );

    my $n;
    no strict 'refs';
    my $rg = qr{\(
    (\w?)[,)]?
    (\w?)[,)]?
    (\w?)[,)]?
    (\w?)[,)]?
    ,\s+
    (??{ scalar(grep ${$_} ,1..@+) })
    $
    }x;

    print "\n$_" for grep /$rg/, @strings
    ....

    which is still simple and will work up to four
    "entities". To make a more comprehensive version -
    is left to you ;-)

    The "Trick" is to check the capture groups (\w)
    for 'trueness' (in grep) and take the 'number'
    of positively grepped items as the content
    (will be "2" or "3") of the dynamic regex
    part (??{ ... }).


    Regards

    M.
    Mirco Wahab, Aug 14, 2007
    #14
  15. Morfys

    Bill H Guest

    On Aug 14, 10:24 am, Mirco Wahab <-halle.de> wrote:
    > Morfys wrote:
    > >> I could understand this intended
    > >> to match a string like

    >
    > >> "open(X,X,X), 3"
    > >> or
    > >> "open(X,X), 2"

    >
    > > that's what I meant. ;)

    >
    > OK, then there are some solutions available,
    > my first trial would be something like:
    >
    > ...
    > my @strings = (
    > "open(X,X,X), 1",
    > "open(X,X,X), 3",
    > "open(X,X,X), 31",
    > "open(X,X), 2",
    > "open(X,X), 23",
    > "open(X,X), 32" );
    >
    > my $n;
    > no strict 'refs';
    > my $rg = qr{\(
    > (\w?)[,)]?
    > (\w?)[,)]?
    > (\w?)[,)]?
    > (\w?)[,)]?
    > ,\s+
    > (??{ scalar(grep ${$_} ,1..@+) })
    > $
    > }x;
    >
    > print "\n$_" for grep /$rg/, @strings
    > ...
    >
    > which is still simple and will work up to four
    > "entities". To make a more comprehensive version -
    > is left to you ;-)
    >
    > The "Trick" is to check the capture groups (\w)
    > for 'trueness' (in grep) and take the 'number'
    > of positively grepped items as the content
    > (will be "2" or "3") of the dynamic regex
    > part (??{ ... }).
    >
    > Regards
    >
    > M.


    I know this may not be the most elegant way of doing it, but, using
    the examples given couldn't you just do this:

    my @strings = (
    "open(X,X,X), 1",
    "open(X,X,X), 3",
    "open(X,X,X), 31",
    "open(X,X), 2",
    "open(X,X), 23",
    "open(X,X), 32" );

    foreach $temp (@strings)
    {
    @dbf=split(/\,/,$temp);
    $numpart[@numpart] = $dbf[@dbf - 1];
    }

    And @numpart would hold all the decimal parts.

    Bill H
    Bill H, Aug 14, 2007
    #15
    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. Jay Douglas
    Replies:
    0
    Views:
    598
    Jay Douglas
    Aug 15, 2003
  2. Alec S.
    Replies:
    10
    Views:
    10,120
    Alec S.
    Apr 16, 2005
  3. =?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunino?=

    Position of test values in conditional expressions

    =?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunino?=, Jun 20, 2004, in forum: C++
    Replies:
    23
    Views:
    699
    Programmer Dude
    Jun 28, 2004
  4. Ion Freeman
    Replies:
    3
    Views:
    352
    Martin Gregorie
    Jul 24, 2009
  5. Noman Shapiro
    Replies:
    0
    Views:
    232
    Noman Shapiro
    Jul 17, 2013
Loading...

Share This Page