Alex028502
Alex028502

Reputation: 3814

using head -n1 to get first match of grep on osx

I am trying to use head -n1 to get just the first grep match (which is suggested a few places)

I expect this to work

$ printf "x=0;\nwhile True:\n x+=1\n print x" | python | grep -w 333 | head -n1

(pipe something that goes on forever into a grep command that will select a single line, and then take the first line from that output)

However, there is no output, and it never stops.

This works as expected: (take first line of infinite output, without grep)

$ printf "x=0;\nwhile True:\n x+=1\n print x" | python | head -n1
1
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
IOError: [Errno 32] Broken pipe

And this works: (grep the output and get a single match)

$ printf "x=0;\nwhile True:\n x+=1\n print x" | python | grep -w 333
333

(and never exits)

However, this combination doesn't give me what I would expect:

$ printf "x=0;\nwhile True:\n x+=1\n print x" | python | grep -w 333 | head -n1

(never prints anything and never exits)

Upvotes: 2

Views: 1805

Answers (2)

anubhava
anubhava

Reputation: 785276

You need to use --line-buffered option in grep:

printf "x=0;\nwhile True:\n x+=1\n print x" | python | grep --line-buffered -w 333 | head -n 1
333

As per man grep:

--line-buffered
     Force output to be line buffered.  By default, output is line buffered when standard
     output is a terminal and block buffered otherwise.

However note that command won't exit since you are running an infinite loop in python code.

If you want your pipeline to exit immediately after printing first match then use awk:

printf "x=0;\nwhile True:\n x+=1\n print x" | python |& awk '$1=="333"/{print; exit}'
333

Upvotes: 3

muru
muru

Reputation: 4897

BSD grep on macOS > 10.9 supports the -m option:

-m num, --max-count=num
     Stop reading the file after num matches.

So you can skip the head and use -m1:

$ printf "x=0;\nwhile True:\n x+=1\n print x" | python | grep -w 333 -m1
333
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>

Upvotes: 2

Related Questions