--invert-match / -v is broken #75

sjl opened this Issue Sep 22, 2012 · 15 comments


None yet

6 participants

sjl commented Sep 22, 2012

So I'm guessing not many people use ag with inverted matching. Right now:

$ echo foo >> sample
$ echo bar >> sample

$ ag foo sample

$ ag -v foo sample

$ ag -v bar sample

$ ag -v b sample

$ mkdir test
$ cd test
$ echo foo >> sample

$ ag -v foo
ggreer commented Sep 22, 2012

Yeah, invert_matches() in util.c screws up if there are matches at the very start or end of a file. I know it's egregious, but it took 7 months for anyone else to notice.

I'm kinda busy today and tomorrow, but I think I can get around to this on Monday.

ggreer commented Oct 7, 2012

One of these Mondays....

@ggreer ggreer referenced this issue Oct 8, 2012

Fix invert_matches #88

ggreer commented Oct 8, 2012

Try master now. There's one tricky thing though: Newlines count as "not foo". I'm thinking I should change this behavior to be more intuitive. Still, it's better than it used to be.

ggreer commented Oct 9, 2012

I looked at ack --help and noticed -v is only supposed to print non-matching lines. Whoops. That makes it much more useful, but I need to change ag to behave that way.

danielb2 commented Oct 3, 2013

👍 I always end up having to use grep's grep -v because the behavior of ag is way different. I'm hoping for ag to be a one-stop-shop

I use it very often to filter matching results: for example, I want all files matching foo, but ignoring any results that are in folder bar...

ag foo | grep -v bar

tsibley commented Dec 12, 2013

I'm used to grep -v and just ran into this issue with ag today. An example:

screen shot 2013-12-12 at 13 36 43

Note the extra brokenness at the end, represented by my terminal as ^@. It's a null byte in a hexdump.

I'm willing to do or help do the work to make ag behave correctly like ack/grep. @ggreer, can you give me any pointers to what needs to change before I dig in?

tsibley commented Dec 12, 2013

Hmm, I see that #88 does note that printing bugs were probably introduced. I guess the null byte is one of them.


The first thing I see is that matches[], when passed into print_file_matches(), contains start and ends which correspond to matching bytes (not lines), which is reflected in the colored-printing nicely:


however, because of this, the unwanted lines are not ignored within the newline-parse/print code around print.c:114 like they are for the normal string match, since there is technically a matching byte in each line.

I have started hacking in some code which uses more looking-behind and ahead to see which lines should actually be thrown out. But I think a nicer long-term solution would be to change the matches[].start and end indices to exclude the partial/matched-by-reverse lines so that the printing code can be simplified.


@ggreer any progress on this? I really miss the non-matching lines

As you correctly observed, it's a lot more useful that way.

nodakai commented Aug 15, 2014

@danielb2 all the above issues were already fixed as of today (ag version 0.24.1)

$ cat foobar.dat 
foo 1
bar 1
asdfbar 2
foo 2
bar 3
foo 3

$ ag 'bar' foobar.dat 
2:bar 1
3:asdfbar 2
5:bar 3
$ ag -v 'bar' foobar.dat 
1:foo 1
4:foo 2
6:foo 3
$ ag 'bar' foobar.dat | ag -v as
2:bar 1
5:bar 3
$ cat test.dat 
1000 2013-12-11 2013-12-11
1000 2013-12-11 2013-12-11:2013-12-10
1000 2013-12-11 2013-12-10
1000 2013-12-11 ?
$ ag '^\d+ (\S+?) \1$' test.dat 
1:1000 2013-12-11 2013-12-11
$ ag -v '^\d+ (\S+?) \1$' test.dat 
2:1000 2013-12-11 2013-12-11:2013-12-10
3:1000 2013-12-11 2013-12-10
4:1000 2013-12-11 ?
$ ag -v '^\d+ (\S+?) \1$' test.dat | xxd
0000000: 323a 3130 3030 2032 3031 332d 3132 2d31  2:1000 2013-12-1
0000010: 3120 3230 3133 2d31 322d 3131 3a32 3031  1 2013-12-11:201
0000020: 332d 3132 2d31 300a 333a 3130 3030 2032  3-12-10.3:1000 2
0000030: 3031 332d 3132 2d31 3120 3230 3133 2d31  013-12-11 2013-1
0000040: 322d 3130 0a34 3a31 3030 3020 3230 3133  2-10.4:1000 2013
0000050: 2d31 322d 3131 203f 0a                   -12-11 ?.



👍 Love it. The highlighting is a bit weird would be my only feedback.

$ echo -e "blah foo blah\nfoo bar" > out.txt
$ ag bar out.txt | ag -v blah
2:foo bar

The whole foo bar is highlighted. It's easier to see if nothing is highlighted since usually the grep result from -v results in a lot of highlighted text.

nodakai commented Aug 24, 2014

@danielb2 I also found highlighting under -v odd, but I guess we should file a new issue, since this thread is rather long now


@nodakai good point. See #478


btw, it think this can be closed now?

ggreer commented Aug 31, 2014

I think it can. Thank you everyone for your contributions.

@ggreer ggreer closed this Aug 31, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment