Posts Tagged ‘regex’

ack is better than grep

April 16, 2010 Leave a comment

Disclaimer – this post will probably only make sense if you’re a Linux/UNIX command line freak. So if you’re a Windows .NET programmer or a Web coder or not a coder at all – you might wanna skip this post.

If you spend much time at all working with source code (C, C++, Java, Ruby, Perl, Python, whatever), you quickly come to realize that navigating through code is tricky. Visual Studio users don’t really appreciate this because IntelliSense hides most of this trouble from you (most of the time), but any good UNIX geek knows what a nightmare grep can be and what an unholy combination of pipe magic is required to find your way around code.

I’ll post soon about ctags, cscope and maybe even code bubbles, and how you can use them in combination with the world’s best text editor (vim of course) to write some rockin’ good code.

However, these and other tagging based tools usually require integration with an editor, and there are times where it’s just not convenient to launch or configure an editor. Or setup a project in an IDE. Sometimes you just want to find out what file function Foo is defined in, or who all the callers of Bar are, and you want the answer now.

A naive grep based approach starts out like this:

$   grep "Foo" *
Binary file stuff.o matches
foo.c:247      Foo(bar, car, star);
(5 pages of irrelevant garbage cut)

Usually, you pick up some garbage coming from Binary files in the same directory, and you forget to specify a recursive search so it doesn’t find the file you really wanted.

So, you monkey around some more, use find to limit your search to source files, and you get this:

$   find . -name "*.c" -or -name "*.h" | grep Foo
foo:c:247    Foo(bar, car, star);
subdir/proj/main.c:17    bar = malloc(sizeof(Foo));
.svn/blah/foo.c.blah   Foo(NULL, car, bar);
(Cut 10 pages of irrelevant SVN metadata)

Oops, looks like we got some subversion working copy junk mixed in with useful results. Blasted revision control always clutters up a grep chain. After a few more iterations, my grep command finally ends up looking like this:

$   find . -name "*.c" -or -name "*.h" | grep Foo | grep -v .svn | grep -v otherstuff

It’s honestly a flipping nightmare.

A few months back, I stumbled across another command line tool (well, perl script really) that hides all the warts of grep, and helps me do the one task I really care about doing: finding everyone who uses Foo so I can add a new parameter to the argument list, or some other similar code maintenance task.

Now, instead of typing a monstrous, iterative grep session – I just type

$   ack Foo

And ack searches for the regular expression Foo in all source-code-like files in all subdirectories, displaying line numbers and highlighting in red the matching patterns.

ack really is better than grep.

ack rocks. Save yourself a lot of grief and kick your grep habit to the curb, you will never look back.



Categories: Uncategorized Tags: , ,