3

Output of just the ping command:

[root@servera ~]# ping -c 4 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=8.04 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=128 time=7.47 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=128 time=7.72 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=128 time=7.50 ms --- 8.8.8.8 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3007ms rtt min/avg/max/mdev = 7.473/7.683/8.037/0.225 ms 

I want to just capture the integer 4 from the "4 received".

ping -c 4 8.8.8.8 | awk -F ',' '/received/ { print $2 }'

The result is 4 received. I want to capture just the number 4 from the above command. How can I do that? The delimiter is space now.

0

8 Answers 8

10

All you need is:

awk '/received/{print $4}' 

e.g. using cat file to get the same input for awk as in your question:

$ cat file PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=8.04 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=128 time=7.47 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=128 time=7.72 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=128 time=7.50 ms --- 8.8.8.8 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3007ms rtt min/avg/max/mdev = 7.473/7.683/8.037/0.225 ms 

$ cat file | awk '/received/{print $4}' 4 

Obviously just replace cat file with ping -c 4 8.8.8.8 for your real testing.

In response to the OPs comment below asking what line it's matching on:

$ awk '/received/' file 4 packets transmitted, 4 received, 0% packet loss, time 3007ms 

and why field number 4 is the one to print:

$ awk '/received/{for (i=1; i<=NF; i++) print i, "<" $i ">"}' file 1 <4> 2 <packets> 3 <transmitted,> 4 <4> 5 <received,> 6 <0%> 7 <packet> 8 <loss,> 9 <time> 10 <3007ms> 
3
  • Can you explain how the integer 4 aligns to fourth field? When you do {print $4}, which line and which filed number is it printing ? Just want to understand the process. Commented Apr 5, 2022 at 0:45
  • 1
    On the line: 4 packets transmitted, 4 received, 0% packet loss, time 3007ms field 1. 4 field 2.packets field 3. transmitted, field 4. 4 The awk is selecting the line that matches received Commented Apr 5, 2022 at 1:36
  • 1
    @Cruise5 I added a breakdown of what the script is doing at the end of my answer. Commented Apr 5, 2022 at 11:11
7

There is another way to do this with awk (similar to comment on one of the answers)

awk -F, '/received/ {print int($2)}' 

function int() will "discard" nonnumber information after the first number

1
  • 5
    Or $2+0 should work too, +1 anyway Commented Apr 4, 2022 at 17:12
7

You have already gotten some fine awk answers, so here are a few alternatives.

  1. GNU grep

    $ ping -c 4 8.8.8.8 | grep -oP '\d+(?= received,)' 4 
  2. Perl

    $ ping -c 4 8.8.8.8 | perl -lne 'print $1 if /(\d+) received,/' 4 
  3. sed

    $ ping -c 4 8.8.8.8 | sed -En 's/.*, ([0-9]+) received,.*/\1/p' 4 
6

The field separator can be a regular expression, so you can set multiple field delimiters in awk using [ ] such as:

awk -F '[, ]' '/received/ {print $5}' 

However in this case I would probably just remove the word received:

 awk -F, '/received/ {sub(/received/, "", $2); print $2}' 

The awk sub() function sub(regexp, replacement [, target]) will find the pattern represented by the regular expression, replace it with replacement, and can optionally be narrowed to a target column.

6
  • 3
    I wonder if it would anger the awk gods if you simply forced numeric conversion of the field i.e. awk -F, '/received/ {print $2+0}' ? Commented Apr 4, 2022 at 16:41
  • What is the function of sub and "" in the parenthesis)? Commented Apr 4, 2022 at 17:39
  • /received/ {sub(/received/, "", $2); print $2} = sub(/received/, ""){print $2} in this case, but it still leaves undesirable blanks either way. Commented Apr 4, 2022 at 17:40
  • +1 for answering the question as asked, rather than providing workarounds. You never know when someone will actually need 2 separate delimiters an stumble on this thread. Commented Apr 5, 2022 at 14:09
  • 1
    @shadowtalker Conversely, sometimes they're asking the wrong question, i.e. it's an XY problem. Commented Apr 6, 2022 at 14:51
3
 ping -c4 <ipadress>|awk '/received/{for(i=1;i<=NF;i++){if($i ~ /received/){print $(i-1)}}}' 

output

4 
0
2

All of the answers here are good at addressing OP's specific rqeuirements.

However, none of them address the general question of splitting a field on a delimiter other than the "main" delimiter used by the main AWK loop.

The answer is to use the split() function, available in all AWK versions that I know of, including the One True AWK and the POSIX specification:

/received/ { split($2, recv, " "); print(recv[1]) } 

This emits 4 on stdout:

awk -F ',' ' /received/ { split($2, recv, " "); print(recv[1]) } ' <<\EOD PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=8.04 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=128 time=7.47 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=128 time=7.72 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=128 time=7.50 ms --- 8.8.8.8 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3007ms rtt min/avg/max/mdev = 7.473/7.683/8.037/0.225 ms EOD 

Note split() has the same semantics as top-level record splitting with FS. That is, it should behave exactly like a second delimiter. This is implied by (but not explicitly stated in) the POSIX specification, and is explicitly stated in the GNU AWK manual page. The main effect of this that (like FS) if the separator pattern is " ", leading and trailing whitespace is stripped and consecutive whitespace characters are treated as single spaces.

0
1

Bash command line:

recv=( $(ping -c 4 8.8.8.8 | grep received) ); echo ${recv[3]} 

Capture the result of 'ping' piped to 'grep' as the array 'recv'; display the 3rd element of the array.

Output:

4 
0

Or do it in the most awk fashion without physically counting fields :

mawk NF RS='^.+tted,[ \t]*|[ \t]*recei.+$' testfile4.txt 4 

If you use the quick printout feature from gawk, you can see that RT matches the entire tail of it :

RT: " received, 0% packet loss, time 3007ms\nrtt min/avg/max/mdev = 7.473/7.683/8.037/0.225 ms\n" 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.