gogolb
gogolb

Reputation: 65

Parsing of ip address from netstat output on MacOS with awk

This is an awk related question (no perl/cut/sed... please :) ).

What I'm actually trying to do is to get the destination address from netstat output on MacOS using only awk.

Here an example of the output:

$ netstat -nl -p tcp
Active Internet connections
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
tcp4       0      0  127.0.0.1.26164        127.0.0.1.50100        ESTABLISHED
tcp4       0      0  127.0.0.1.50100        127.0.0.1.26164        ESTABLISHED

If I run the awk parser, I get :

$ netstat -nl -p tcp | awk '/tcp/ {split($5,a,".") ; for(i=1; i<NF-1; i++) printf a[i] "."; printf "\n"}'
127.0.0.1.
127.0.0.1.

1) Is there a way to remove the "." at the end of the IP address?

2) Is there a better "awk" way to obtain the same result?

PS: I know you can type something like

$ netstat -nl -p tcp | perl -ape '$_=$F[4];s/((?:\d+\.){3}\d+)\D.*/$1\n/'

to get the correct result ;)

Thanks!

Upvotes: 1

Views: 662

Answers (5)

terdon
terdon

Reputation: 3380

Why not do it the UNIX way? Pipe it to another utility:

netstat -nl -p tcp | awk '/tcp/{print $4}' | sed 's/\.[0-9]*$//'

Or, to do the whole thing in awk, use sub() to delete the last part of the IP:

netstat -nl -p tcp | awk '/tcp/{sub(/\.[0-9]*$/,"",$4); print $4}' 

Unfortunately, BSD grep (which is what OSX has) does not have the -P option, else you could do:

netstat -nl -p tcp | awk '/tcp/{print $4}' | grep -oP '.*(?=\.\d+)'

Upvotes: 1

user3442743
user3442743

Reputation:

I think this is the easiest and most general way to do this using awk

 awk '{match($5,/(.*)\./,x);print x[1]}' file

Upvotes: 1

Mark Setchell
Mark Setchell

Reputation: 207798

I think I prefer this approach with multiple alternative FS - either dot or space:

netstat -nl -p tcp |awk -F'[. ]*' '/tcp/{print $9,$10,$11,$12}' OFS="."

Upvotes: 1

confused00
confused00

Reputation: 2612

The other reply is probably better but here's my attempt:

netstat -nl -p tcp | awk '/tcp/{split($5,a,".");for(x in a)if(a[x+1]""){y=y SEP a[x]; SEP="."}print y;y="";SEP=""}'

Explanation

  • if(a[x+1]"") checks if there is a next element in an array (i.e. if it's not processing the last element - the port) and the "" converts the number into a string by applying concatenation so 0 doesn't evaluate to False
  • The SEP variable just makes sure the output won't start with a ., and gets reset at the end.

Upvotes: 1

fedorqui
fedorqui

Reputation: 290235

Just play with the number of elements coming from split():

awk '/tcp/ {n=split($5,a,".")
            ^-----------------------------------------------------------\
            for(i=1; i<n; i++) printf "%s%s", a[i], (i==n-1?"\n":".")   |
                       ^-----------------------------^^^^^^-------------/
           }'

Explanation

  • n=split($5,a,".") split as you were doing, but storing in the variable n the amount of fields that this produces.
  • for(i=1; i<n; i++) printf "%s%s", a[i], (i==n-1?"\n":".")} loop through these values, printing either a dot . or a new line depending on the loop time.

Test

$ netstat ... | awk '/tcp/ {n=split($5,a,"."); for(i=1; i<n; i++) printf "%s%s", a[i], (i==n-1?"\n":".")}'
127.0.0.1
127.0.0.1

Upvotes: 1

Related Questions