SpaghettiCat SpaghettiCat - 2 months ago 6
Bash Question

How to specify an ignore pattern with ack?

I'm trying to search for lines containing 'foo' but these lines must not contain 'bar'. What's a good way to search with these parameters with

ack
?

I can do:

ack "foo" | grep -v "bar"


but it doesn't keep the nicely layed-out and coloured output of
ack
. Also,
grep
doesn't have good support for Perl regexes, unlike
ack
.

Answer

You can use a slightly more complicated regular expression:

ack '^(?!.*bar).*(foo)' file

The (?!...) does a negative lookahead to ensure that "bar" is not on the line. Here's how it works:

  • ^ Start at beginning of the line.
  • (?!.*bar) Advance any number of characters until "bar" is found. If it is found, do not continue. Otherwise, return to the start of the line and continue.
  • .*(foo) Match (and capture) "foo" at any point between the beginning and end of the line.

Testing it out:

$ cat file
other foo bar
baz foo other
$ ack '^(?!.*bar).*(foo)' file
baz foo other