7

Is it possible (and how) to chain patterns with ack (ack-grep on some distributions of Linux) like I'm used to with grep?

e.g.

grep "foo" somefile.c | grep -v "bar"

...to match all lines with "foo" but without "bar".

Andy Lester
  • 91,102
  • 13
  • 100
  • 152
scrrr
  • 5,135
  • 7
  • 42
  • 52

1 Answers1

11

ack uses Perl regular expressions, and those allow lookahead assertions:

^(?!.*bar).*foo.*$

will match a line that contains foo but doesn't contain bar.

I'm not familiar with the usage of ack, but something like this should work:

ack '^(?!.*bar).*foo.*$' myfile
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • The problem with this is if the file does not have `bar` in it, the search for `foo` is not even tried. – Anthony Hatzopoulos Nov 24 '15 at 18:01
  • @AnthonyHatzopoulos: Why would that be a problem? – Tim Pietzcker Nov 24 '15 at 18:06
  • OP is looking for lines with foo. And then they don't want to return those lines with bar on them. I think it just so happened that the file had bar in it, that they got what they wanted. Although it will not return files with only foo. Say I'm looking for all `foo()` but not `foo(bar)`, I still want all my other *foos*. In my case `somefile.c` is an entire project. Just though it was worth mentioning. – Anthony Hatzopoulos Nov 24 '15 at 18:16
  • No. First, `.` doesn't match newlines, so the lookahead would always only look ahead for one line. But this doesn't matter with `ack` since it operates line by line anyway. It never looks at the entire file. – Tim Pietzcker Nov 24 '15 at 18:18
  • I apologize you're right Tim. That method you does indeed work. In a simpler test it worked for me. I've made a mistake with my own additions to my use case. +1 – Anthony Hatzopoulos Nov 24 '15 at 18:31
  • In my case I was using the `-l` option to "Only print filenames containing matches" and it did not work. – Anthony Hatzopoulos Nov 24 '15 at 18:47