给定 nmap 针对子网的输出
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)
目标是获得 csv 或任何其他分隔格式的输出:
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
...
上述工作已使用 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
问题是 可以将上述两步 awk 过程合并为一个 awk 命令吗?感谢您事先提供的所有信息
编辑 尝试通过一些变化来巩固这两个步骤
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)
前景并不乐观。 AWK 总是会给出一个很好的理由来解释为什么在 END 和 BEGIN 之间的间隙停止处理。该练习实际上是尝试创建一个(bash)函数,该函数能够渲染重复模式中的任何数据,nmap 输出只是一个示例。
答案1
正常的做法是将所有行中所需的信息存储到 awk 变量中,然后打印块中最后一行的数据。因此,对于示例,您将拥有类似的内容(我没有对主机关闭延迟情况进行编码,因为示例数据没有显示它)。
nmap -sP 192.168.1.0/24 -n --max-rtt-timeout 50ms |
awk '/Nmap scan report for / {ip=$5}
/Host is up/ { latency=$4 ; sub(/(/,"",latency) }
/MAC Address: / { mac=$3; print(ip "," mac "," latency) ; ip=mac=latency="unknown" }
BEGIN { print "IP,MAC,RTT"}
可能需要也可能不需要清除块最后一行中的变量,具体取决于数据是否始终完整。如果有很多变量,请考虑使用数组而不是像ip
,之类的标量变量mac
,latency
因为这些变量都可以通过一次删除来清除。