Bash:循环多个输入源(嵌套“读取时”循环?)

时间:2015-08-03 15:35:17

标签: bash

我有一个运行query.sh命令的dig脚本,从不同的DNS服务器执行一组查找,这些查询当前在所使用的单个输入文件的列中给出(sites.txt )。

我的目标是修改此脚本以使用不同的输入文件dns_servers.txt来查找要为每个查询迭代的DNS服务器。

我不知道从哪里开始。为了能够安全地嵌套while read循环,我需要做什么?

当前输入:

query.sh

#!/bin/sh

while read line;
do
        set $line
        echo "SITE:" $1@$2
        /usr/sbin/dig +short -4 @$2 $1
        sleep 5
        exitStatus=$?
        echo "Exit Status: " $exitStatus
done < sites.txt

sites.txt

当前格式具有主机名和DNS服务器,用于针对该主机名进行查找。

www.google.com 8.8.4.4

意图是忽略DNS服务器的列,而改为使用dns_servers.txt的内容。

期望的输入

的dns_servers.txt

10.1.1.1
12.104.1.232
...

1 个答案:

答案 0 :(得分:5)

忽略sites.txt文件中的任何其他列,并遍历dns_servers.txt行,可能如下所示:

#!/bin/sh
while read -r site _ <&3; do
  while read -r dns_server <&4; do
    dig +short -4 "@$dns_server" "$site"; exit=$?
    sleep 5
    echo "Exit status: $exit"
  done 4<dns_servers.txt
done 3<sites.txt

这里的关键变化:

  • 将要解析的字段列表作为参数传递给read。作为第一个read的第二个位置参数传递的下划线是现在保存site.txt的第二列的变量名。
  • 嵌套你的循环,因为你想从内循环读取外循环的每一遍。
  • 对外部和内部循环使用不同的文件描述符(此处为34)以保持它们分开。

顺便提一下,如果你的目标是bash(#!/bin/bash)而不是POSIX sh(#!/bin/sh),我可能会采用不同的方式。以下使用bash 4扩展程序mapfile一次性读取dns_servers.txt

#!/bin/bash
readarray -t dns_servers <dns_servers.txt
while read -r site _; do
  for from_ip in "${dns_servers[@]}"; do
    dig +short -4 "@$from_ip" "$site"; exit=$?
    sleep 5
    echo "Exit status: $exit"
  done
done <sites.txt

在这里,我们只阅读dns_servers.txt一次,并为从sites.txt读取的每个值重用该值列表。

如果你正在使用bash 3.x,mapfile可以用循环代替:

dns_servers=( )
while read -r; do dns_servers+=( "$REPLY" ); done <dns_servers.txt