grep nmap 输出,有条件地打印选定的行

dud*_*ude 1 linux bash grep nmap

我正在尝试编写一个 bash 脚本,该脚本将读取 .txt 文件中的一系列 ip 地址,并将使用 NSE(smb-os-discovery ) 脚本。从这个输出中,我只想打印某些行,但前提是其中之一与特定模式匹配。

我尝试了多种不同的选项,但无法让它按照我的意愿工作,因为我要检查和输出的两个项目在两个不同的行中。我设法得到的最接近的是编写以下 bash 脚本:

#!/bin/bash
for server in $(cat servers-smb.txt); do
nmap --script smb-os-discovery $server | grep "report\|OS: Windows"
done
Run Code Online (Sandbox Code Playgroud)

运行上面的脚本时,输出有运行 Windows 的服务器,但也有 report,这是预期的,因为 grep 表达式包含一个“OR”运算符。

对此的任何帮助将不胜感激。

tri*_*eee 5

grep 不容易适应你想要的东西,但 awk 是天作之合。

#!/bin/sh
while read server; do
   nmap --script smb-os-discovery "$server" |
    awk '/report/ { r=$0 } /OS: Windows/ { print r; print; exit }'
done <servers-smb.txt
Run Code Online (Sandbox Code Playgroud)

Awk 脚本收集报告行,如果它与“OS: Windows”匹配,则将其与 OS: 行一起打印。

还要注意改变的 shebang(在这个脚本中没有任何 Bash 特定的东西,所以最好用 plain 运行它sh),优先使用whileover for+ Uselesscat"$server"在循环内部正确引用,最后在控件中使用正确的缩进块以提高可读性。

一种不太吸引人的方法是将两个greps串起来。我在这里提到它是为了完整性——任何不止一个的东西grep作为 Awk 或sed脚本可能会更好。

grep "report\|OS: Windows" | grep -B1 "OS: Windows"
Run Code Online (Sandbox Code Playgroud)

最后,使用 just 实现相同结果的一种简单方法grep是将 IP 地址添加到输出中,因为server变量中已经有了它。

while read server; do
    nmap --script smb-os-discovery "$server" |
    # XXX: suboptimal; see below
    grep "OS: Windows" | sed "s/^/$server:/"
done <servers-smb.txt
Run Code Online (Sandbox Code Playgroud)

但当然,grep | sed也是一种反模式,最好仅表示为sed脚本:

while read server; do
    nmap --script smb-os-discovery "$server" |
    sed -n "/OS: Windows/s/^/$server:/p"
done <servers-smb.txt
Run Code Online (Sandbox Code Playgroud)

这具有在一行上收集一台主机的输出的额外好处,这使其更适合使用典型的 Unix 面向行的工具进行额外处理。