cspctec has asked for the wisdom of the Perl Monks concerning the following question:

I have the following array:
my @data = ('scp', 'sss40s1u01:/home/example/test.txt', '/home/example +/testdir');
And I'm trying to create a regex to match "/home/example/testdir" and NOT any part of "sss40s1u01:/home/example/test.txt". I'm having some trouble coming up with a regex for this. So far, I have tried negative lookbehind:
foreach (@data) { my $match = $_ if /(?<!:)\/.+/; }
But that matches "sss40s1u01:/home/example/test.txt" also.

I would appreciate any help.

Replies are listed 'Best First'.
Re: Help with a small regex
by hippo (Archbishop) on Feb 06, 2015 at 18:09 UTC

    If you really only want to test for "/home/example/testdir" then this should work:

    foreach (@data) { my $match = $_ if /testdir/; }

    OTOH, if the spec is actually to match against just a path then this should do:

    foreach (@data) { my $match = $_ if /^\//; }
Re: Help with a small regex
by kennethk (Abbot) on Feb 06, 2015 at 18:14 UTC
    The most obvious difference to me is the presence of a colon, which seems to be what you've used in your own logic. How about instead of returning true if it contains no colon, you try returning false if it contains one?
    foreach (@data) { my $match = $_ if !/:/; }
    The issue you are having is that you need the entire string to contain no colons, but what you have tested for is actually that it contains non-colon characters. The closest code to your spec would be
    foreach (@data) { my $match = $_ if /^[^:]*$/; }
    which says that all characters between the start and end of the string are not colons.

    Advanced use case, this is exactly the sort of thing grep was made for:

    my ($match) = grep !/:/, @data;

    Update: Fixed typo in case two; thanks AnomalousMonk.


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

Re: Help with a small regex
by cspctec (Sexton) on Feb 06, 2015 at 21:02 UTC
    Thanks for the help you two. I forgot to mention that "testdir" can and will change (the matches definitely won't contain "testdir"). Your solutions work, but they also match "scp". I just added
    next if /scp/;
    to the loop along with if !/:/ to fix it.

      I don't see why hippo's second second suggestion above (the OTOH one) would not cover all your cases:

      c:\@Work\Perl\monks>perl -wMstrict -le "for my $path ( 'scp', 'sss40s1u01:/home/example/test.txt', '/home/example/testdir' +, @ARGV, ) { print qq{'$path' matches} if $path =~ /^\//; } " "/any" "/other/examples" '/home/example/testdir' matches '/any' matches '/other/examples' matches
      (BTW: My own preference for the regex expression would be  m{ \A / }xms rather than  /^\//)


      Give a man a fish:  <%-(-(-(-<