Given the output of nmap against a subnet
Nmap scan report for 192.168.1.20
Host is up (0.010s latency).
MAC Address: EC:13:B2:E2:20:48 (Netonix)
Nmap scan report for 192.168.1.21
Host is up (0.010s latency).
MAC Address: EC:13:B2:E2:13:68 (Netonix)
Nmap scan report for 192.168.1.23
Host is up (0.010s latency).
MAC Address: EC:13:B2:E1:AE:A8 (Netonix)
Nmap scan report for 192.168.1.99
Host is up (0.00076s latency).
MAC Address: 90:6C:AC:48:86:DA (Fortinet)
The goal is to get an output for csv or any other delimited format:
IP,MAC,RTT
192.168.1.20,EC:13:B2:E2:20:48,0.010s
192.168.1.21,EC:13:B2:E2:13:68,0.010s
...
The above has been accomplished in a two step process using AWK
$time_date=$(date "+%Y-%m-%d_%T") # Get the immediate date and time
$nmap_command=$(nmap -sP 192.168.1.0/24 -n --max-rtt-timeout 50ms)
# Concatenate all lines including and between the patterns "Nmap scan report for"
c_list=$((awk '/Starting|done:/ {next} /Nmap scan report for/{ if (x) print x; x=""; }{ x=(!x)?$0:x" "$0; }END{ print x; }')<<<$nmap_command)
# Extract the values of interest from each line, add a header line, then add delimiter for every value extracted
list=$((awk -v OFS=',' -v date=$time_date 'BEGIN{ print "Date,IP,MAC,RTT" };{ gsub(/[()]/,""); for (I=1;I<=NF;I++) if ($I == "for") ip=$(I+1); else if ($I == "up") lat=$(I+1); else if ($I == "Address:") mac=$(I+1); } { print date, ip, mac, lat }')<<<$c_list)
printf '%s\n' "$list" > ~/Desktop/list.csv # Send output to file
exit 0
The question is can the above two step awk process be consolidated into a single awk command. Thank you for the all the input beforehand
EDIT attempts to consolidate the two step with a some variations of
x_list=$((awk '/Starting|done:/ {next} /Nmap scan report for/{ if (x) print x; x=""; }{ x=(!x)?$0:x" "$0; }END I=x BEGIN{ print "Date,IP,MAC,RTT" };{ gsub(/[()]/,""); for (I=1;I<=NF;I++) if ($I == "for") ip=$(I+1); else if ($I == "up") lat=$(I+1); else if ($I == "Address:") mac=$(I+1); } { print date, ip, mac, lat }')<<<$list_ips)
was not promising. AWK would always give a good reason why to cease processing at the gap between the END and BEGIN. The exercise is actually an attempt to create a (bash) function that would be able to render down any data that is in a repeating pattern, the nmap output is just an example.
-oX
(XML) output, then parsing that with something likexmlstarlet
instead. See for example Parsing Nmap's XML output with XMLStarlet