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

Hi all, I am trying to take an expression in shell that works for me and translate it into Perl however it is giving me fits! Basically I'm trying to grep out all instance of /usr, /platform, /sbin and /lib in a file and return all other lines to a file. This is the bit that strips out the exceptions:

egrep -v '^/usr$|^/sbin$|^/platform$|^/lib$' <file name>

In Perl I have tried:

grep /!^(\/usr|\/sbin|\/platform|\/lib)$/

This didn't do it. Tried many variations that ended in error. Any help on this would be greatly appreciated!

Replies are listed 'Best First'.
Re: Using grep to find "/<file system"
by choroba (Cardinal) on Oct 14, 2011 at 12:51 UTC
    grep in Perl does not operate on files, but on arrays.
Re: Using grep to find "/<file system"
by Eliya (Vicar) on Oct 14, 2011 at 13:03 UTC

    You need to put the negation operator outside of the regex; otherwise, you're telling Perl to look for a literal '!'...

    my @files = qw (/usr /home /sbin /opt/...); my @filtered = grep !/^(\/usr|\/sbin|\/platform|\/lib)$/, @files; print "@filtered\n"; # /home /opt/...
Re: Using grep to find "/<file system"
by hbm (Hermit) on Oct 14, 2011 at 13:43 UTC

    The functional equivalent of your egrep:

    perl -ne 'print if !m#^/(?:usr|sbin|platform|lib)$#' <file name>

    You can write that many different ways; but here, I:

    • changed the delimiter to '#', to avoid escaping '/'
    • grouped the paths with '(?:)' to avoid repeating '^/...$'
Re: Using grep to find "/<file system"
by MidLifeXis (Monsignor) on Oct 14, 2011 at 13:04 UTC

    grep /!^(\/usr|\/sbin|\/platform|\/lib)$/

    grep { ! m(^(/usr|/sbin|/platform|/lib)$) } @files

    See grep.

    --MidLifeXis

Re: Using grep to find "/<file system"
by boneman147 (Initiate) on Oct 14, 2011 at 14:39 UTC

    Many thanks for all the quick replies! I have got it to work using:

    grep !/^(\/usr|\/sbin|\/platform|\/lib)$/, @files;

    Best regards.

      A couple of points regarding the readability of your solution. By choosing a regex delimiter other than the standard '/' you would not have to escape the forward slashes, although you do have to explicitly use the 'm' match operator if not using forward slashes (or question marks, see Regexp Quote-Like Operators in perlop) as the delimiter. Also, the forward slash is common to all of the paths so you could move it out of the alternation. The code becomes

      grep ! m{^/(usr|sbin|platform|lib)$}, @files;

      which to my eye is somewhat clearer!

      I hope this helpful.

      Cheers,

      JohnGG

      mmh... I think this is a work for File:find or opendir/readdir...
Re: Using grep to find "/<file system"
by Anonymous Monk on Oct 14, 2011 at 13:01 UTC
    if (not grep(m{^/(usr|sbin|platorm|lib)$}, @filelist) { ... }