Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Quick Regex trouble

by jrvd (Novice)
on Jul 16, 2013 at 20:38 UTC ( #1044653=perlquestion: print w/replies, xml ) Need Help??
jrvd has asked for the wisdom of the Perl Monks concerning the following question:

Hey monks!

I am trying to just get a regex to work but it doesn't do what I am looking for. I want to match anything that has 'neighbor' but not 'use neighbor'. Also, what is before 'use neighbor' varies so I can't really rely on that.

Here is my test code:

#!/usr/bin/perl use strict; use warnings; my $var = "use neighbor 2001:504:0:4::6181:1"; ($var =~/(?!use) neighbor[[:alpha:]-]* ([[:alnum:]\.-:]+)/) and do{ print $1; };

Any ideas would be greatly appreciated! Thanks and have a nice day!


Replies are listed 'Best First'.
Re: Quick Regex trouble
by kennethk (Abbot) on Jul 16, 2013 at 20:47 UTC
    Close; you need a negative look-behind assertion:
    #!/usr/bin/perl use strict; use warnings; my $var = "use neighbor 2001:504:0:4::6181:1"; ($var =~/(?<!use )neighbor[[:alpha:]-]* ([[:alnum:]\.-:]+)/) and do{ print $1; };

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      NOTEI think it's actually look-behind assertion he needs.

      ($var =~/(?<=use )neighbor[[:alpha:]-]* ([[:alnum:]\.-:]+)/) and do{ print $1; };
      output 2001:504:0:4::6181:1 If that is the output the OP wanted.

      Because with "negative look-behind assertion", the match is not successful (failed). In fact, there is no output.
      Checked with use re 'debug';
      .. produces ..

      NOTE: I think I got this wrong, and kennethk was right! Since, the OP gave a condition on which the regex should match as "when the string doesn't have USE" and the sample he gave has it.

      If you tell me, I'll forget.
      If you show me, I'll remember.
      if you involve me, I'll understand.
      --- Author unknown to me

        I think it's actually look-behind assertion he needs.

        I don't think so. The OP said that it should match "neighbor" but not "use neighbor", so that a zero-width negative look-behind assertion seems to be what is needed to exclude "use".

        Just an additional note: the do {} block is unnecessary in the OP code. The solution could be:

        ($var =~/(?<!use )neighbor[[:alpha:]-]* ([[:alnum:]\.-:]+)/) and print $1;

        or even:

        print $1 if $var =~/(?<!use )neighbor[[:alpha:]-]* ([\d:]+)/;
Re: Quick Regex trouble
by Not_a_Number (Prior) on Jul 16, 2013 at 21:47 UTC

    kennethk++ is right. I'd just like to post a word of warning concerning this part of your regex:


    Firstly, you don't need to escape the dot in a character class (but there's nothing stopping you from doing so...). More importantly, the sequence


    (with or without the backslash) in a character class means "any character between '.' (dot) and ':' (colon) (inclusive)".

    As it happens, the only things in the ASCII (or UTF, or whatever) table between these two characters are the forward slash and the digits 0-9 (the latter being included, of course, in [:alnum:]).

    The point is, that if you want to put a literal hyphen in a character class, you should generally put it at the very beginning or the very end, or else escape it with a backslash.

    Update: Typos (yawn)

Re: Quick Regex trouble
by choroba (Bishop) on Jul 17, 2013 at 07:51 UTC
    Just a note: What should the programme do if a line contains both? E.g.
    qwerty neighbor 12345 use neighbor
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Quick Regex trouble
by hdb (Monsignor) on Jul 17, 2013 at 07:22 UTC

    I would just add another test:

    use strict; use warnings; my $var = "use neighbor 2001:504:0:4::6181:1"; ($var !~ /use neighbor/) and ($var =~/neighbor[[:alpha:]-]* ([[:alnum: +]\.-:]+)/) and do{ print $1; };

    especially as I am not as literate with (negative)? look(back|ahead|around) assertions.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1044653]
Approved by Corion
[LanX]: or two 20 min
[Corion]: IME it doesn't matter whether it's a 20 min talk or 40 min talk ;)
[choroba]: I only applied for 20 minutes this time
[choroba]: I hope it still means I don't have to pay the conference fee
[LanX]: true it's the built up which is stressy
[choroba]: I doubt I can alter my accent beyond Amercian versus British

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2018-04-23 09:32 GMT
Find Nodes?
    Voting Booth?