处理bash中命令输出的每一行

时间:2017-01-18 13:10:38

标签: bash while-loop

从nmap网络扫描输出的每一行,我想将主机及其IP存储在变量中(以便进一步使用"主机已启动" -string):

来自nmap的待处理输出如下所示:

Nmap scan report for samplehostname.mynetwork (192.168.1.45)
Host is up (0.00047s latency).

到目前为止我的剧本:

#!/bin/bash

while IFS='' read -r line
do
  host=$(grep report|cut -f5 -d' ')
  ip=$(grep report|sed 's/^.*(//;s/)$//') 
  printf "Host:$host - IP:$ip"
done < <(nmap -sP 192.168.1.1/24)

输出产生了一些我不明白的东西。它把&#34;主持人:&#34;在一开始,然后它把&#34; IP:&#34;在最后,虽然它完全省略了$ ip的输出。

我的脚本生成的输出是:

Host:samplehostname1.mynetwork
samplehostname2.mynetwork
samplehostname3.mynetwork
samplehostname4.mynetwork
samplehostname5.mynetwork - IP:

在单独的情况下,$ host和$ ip的提取基本上有效(尽管可能有更好的解决方案)。我可以使用printf $ host或$ ip。

我的剧本出了什么问题?谢谢!

2 个答案:

答案 0 :(得分:3)

您的两个grep命令正在从标准输入读取,它们从循环继承,因此它们也从nmap读取。 read获取一行,第一行grep消耗其余行,第二行grep立即退出,因为标准输入已关闭。我怀疑你的意思是grep $line的内容:

while IFS='' read -r line
do
  host=$(grep report <<< "$line" |cut -f5 -d' ')
  ip=$(grep report <<< "$line" |sed 's/^.*(//;s/)$//') 
  printf "Host:$host - IP:$ip"
done < <(nmap -sP 192.168.1.1/24)

然而,这是低效且不必要的。您可以使用bash的内置正则表达式支持来提取所需的字段。

regex='Nmap scan report for (.*) \((.*)\)'
while IFS='' read -r line
do
  [[ $line =~ $regex ]] || continue
  host=${BASH_REMATCH[1]}
  ip=${BASH_REMATCH[2]}
  printf "Host:%s - IP:%s\n" "$host" "$ip"
done < <(nmap -sP 192.168.1.1/24)

答案 1 :(得分:1)

试试这个:

#!/bin/bash
while IFS='' read -r line
do
  if [[ $(echo $line | grep report) ]];then
    host=$(echo $line | cut -f5 -d' ')
    ip=$(echo $line | sed 's/^.*(//;s/)$//')
    echo "Host:$host - IP:$ip"
  fi
done < <(nmap -sP it-50)

输出:

Host:it-50 - IP:10.0.0.10

我添加了一个if子句来跳过不需要的行。