AWK 在提取特定字符串时连接输出行

AWK 在提取特定字符串时连接输出行

给定 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,之类的标量变量maclatency因为这些变量都可以通过一次删除来清除。

相关内容