Behavior of grep -o on OSX

greposx

On Linux, when I do echo foo | grep -o '^.' to get the first character, it prints f as expected. (I know, | cut -c1 would probably be faster.)

But on OSX, doing the same results in 3 matches (3 lines):

f
o
o

WTF? Even without the -o option, the color of the output (in my environment) tells me that the whole line matches, instead of just the first character.

Can anybody please enlighten me?

Best Answer

It's an interesting behavior you've noticed there.

It's wrong to classify it as a "bug" because POSIX doesn't specify a -o option for grep. You may not like how it behaves, and I'll agree that it's annoying that BSD and GNU grep differ, but this behavior is not actually in conflict with what the BSD manual pages say. If you still say it's a bug, well, you know, that's just, like, your opinion, man. :)

Perhaps this alternative presentation will show you why it behaves as it does:

$ echo foofoofoo | grep -o foo
foo
foo
foo

That is, both BSD grep and GNU grep show all of the matching parts of the line, not just the first one. The difference is that BSD grep seems to be implementing that by consuming the matched part and then matching again. When it removes the leading f in your example, it finds that the o following it matches, too, as does the next one.

One fix for this is to install Homebrew, then say brew install grep. This will get you GNU grep as ggrep, so it doesn't collide with the stock version. GNU grep will give the same behavior on my example above, but the two differ for this:

 $ echo foofoofoo | ggrep -o ^foo
 foo

BSD grep will print three foos.

If you replace the stock version with a symlink to ggrep, beware that some OS updates will replace it.

Related Question