Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Negative lookbehind assertion in Perl

Tags:

regex

perl

I have a set of file-paths, and I want to list all file-paths that do not contain x/y/z/. The other constraint is that I cannot use print if !m{x/y/z/} since I don't have write permissions on the script. I can provide the script with regexp patterns to include (as command-line-options), i.e., everything that matches will be printed.

This is my attempt. I am trying to match all lines that do not have x/y/z/ before them.

#!/usr/bin/perl
use warnings;
use strict;

while(<DATA>) {
   print if m{(?<!x/y/z/).*};
}

__DATA__
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/a/b/m.cc
x/y/a/b/m.cc

My expectation is it would print only the bottom two strings, but it prints everything. But when I change the pattern to (?<=x/y/z/).*, it is printing only the top 3 strings:

x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc

Why so, and what should I do to fix my regexp?

like image 946
Unos Avatar asked Oct 06 '22 01:10

Unos


1 Answers

What you need is a negative lookahead. So, straight from the monastery comes the answer:

#!/usr/bin/perl
use warnings;
use strict;

while(<DATA>) {
   print if m{^(?!(?s:.*)x/y/z)}; 
}

__DATA__
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/a/b/m.cc
x/y/a/b/m.cc
like image 187
Tudor Constantin Avatar answered Oct 13 '22 12:10

Tudor Constantin