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

时间:2015-01-22 05:28:49

标签: linux bash grep nmap

我正在尝试编写一个bash脚本,该脚本将读取.txt文件中的一系列ip地址,并将使用NSE(smb-os-discovery)脚本对每个单独的ip执行nmap扫描。从这个输出我想只打印某些行,但只有当其中一行匹配特定模式时。

我已经尝试了多种不同的选项,但只是因为我想要检查和输出的两个项目在两个不同的行中而无法按照我想要的方式工作。 我设法得到的最接近的是写下面的bash脚本:

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

运行上面的脚本时,输出的服务器运行Windows,而report行则不适用,因为grep表达式包含' OR' ;操作

对此的任何帮助都将受到高度赞赏。

1 个答案:

答案 0 :(得分:4)

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

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

另请注意更改后的shebang(此脚本中没有任何特定于Bash的内容,因此也可以使用普通sh运行),while优先于for + { {3}},在循环内正确引用"$server",最后在控制块内使用适当的缩进以便易读。

一种不太吸引人的方法是串联两个grep。我在这里提到它是为了完整性 - 任何具有多个grep的东西可能更好地作为Awk或sed脚本完成。

grep "report\|OS: Windows" | grep -B1 "OS: Windows"

最后,只用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

但当然,grep | sed也是反模式,更好地表达为sed脚本:

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

这样做的另一个好处是可以在一行上收集一个主机的输出,这使得它更适合使用典型的Unix面向行的工具进行额外处理。