Home > database >  Running a command until X number of lines have been obtained in its output
Running a command until X number of lines have been obtained in its output

Time:04-29

While How to Terminate Script after a certain number of output is very similar to what I'm looking for, I noticed that this does not work if I am grepping the output.

For example, this works:

➜  ~ ping google.com | head -n 5
PING google.com (142.251.32.206): 56 data bytes
64 bytes from 142.251.32.206: icmp_seq=0 ttl=115 time=30.867 ms
64 bytes from 142.251.32.206: icmp_seq=1 ttl=115 time=32.049 ms
64 bytes from 142.251.32.206: icmp_seq=2 ttl=115 time=37.133 ms
64 bytes from 142.251.32.206: icmp_seq=3 ttl=115 time=31.965 ms
➜  ~

but what if I want to grep for only lines containing bytes from? This doesn't work (noo output at all):

➜  ~ ping google.com | grep -i "bytes from" | head -n 5

CodePudding user response:

Your second command will eventually produce output, but it will take a while. You are experiencing the results of buffering. From the bash faq:

Most standard Unix commands buffer their output when used non-interactively. This means that they don't write each character (or even each line) immediately, but instead collect a larger number of characters (often 4 kilobytes) before printing anything at all. In the case above, the grep command buffers its output, and therefore awk only gets its input in large chunks.

The same FAQ includes several solutions to this problem. For example, grep has a --line-buffered option that will make your second example work the way you expect:

$ ping google.com | grep --line-buffered -i "bytes from" | head -n 5

CodePudding user response:

Instead of using head, you could limit the number of ping requests:

ping -c 5 google.com

or you could try a

stdbuf -o0 ping google.com

The latter sets the output initially to unbuffered. This assumes that ping behaves nicely and does not set its stdout back to buffered.

  •  Tags:  
  • bash
  • Related