How to include dig lookup in awk?

2.2k views Asked by At

I have an awk command to extract information from mount points (see the accepted answer in How to extract NFS information from mount on Linux and Solaris?):

awk -F'[: ]' '{if(/^\//)print $3,$4,$1;else print $1,$2,$4}

I would like to include a dig lookup in this awk command to lookup the IP of hostnames. Unfortunately, the mount command sometimes include an IP and sometimes a hostname. I tried the following, but it has an unwanted newline, unwanted return code and does not work if there is an IP address:

For hostnames

echo "example.com:/remote/export on /local/mountpoint otherstuff" | awk -F'[: ]' '{if(/^\//)print system("dig +short " $3),$4,$1;else print system("dig +short " $1),$2,$4}'

Returns

93.184.216.119
0 /remote/export /local/mountpoint

For IPs

echo "93.184.216.119:/remote/export on /local/mountpoint otherstuff" | awk -F'[: ]' '{if(/^\//)print system("dig +short " $3),$4,$1;else print system("dig +short " $1),$2,$4}'

Returns

0 /remote/export /local/mountpoint

I would like to retrieve the following in both cases

93.184.216.119 /remote/export /local/mountpoint

Update:

It seems that some versions of dig return the IP when an IP is provided as query and others return nothing.

Solution:

Based on the accepted answer I used the following adapted awk command:

 awk -F'[: ]' '{if(/^\//) { system("dig +short "$3" | grep . || echo "$3" | tr -d \"\n\""); print "",$4,$1 } else { system("dig +short "$1" | grep . || echo "$1" | tr -d \"\n\"");print "",$2,$4  };}'

The additional grep . || echo "$3" takes care that the input IP/hostname is returned if dig returns nothing.

1

There are 1 answers

0
janos On BEST ANSWER

The system command in awk executes a command returns its status. Consider this:

$ awk 'END { print "today is " system("date") " and sunny" }' < /dev/null
Tue Jan  7 20:19:28 CET 2014
today is 0 and sunny

The date command outputs the date and a newline. When running from awk the same thing happens. In this example the system finishes before printf itself, so first we see the line with date, and on the next line our text with the return value 0 of system.

To get what we want we need to split this into multiple commands and we don't need the return value of system:

$ awk 'END { printf "today is "; system("date | tr -d \"\n\""); print " and sunny" }' < /dev/null
today is Tue Jan  7 20:24:01 CET 2014 and sunny

To prevent the newline after date, we piped its output to tr -d "\n".

Long story short, change from this:

print system(...), $2, $4

to this:

system(... | tr -d \"\n\"); print "", $2, $4