Bash:循环多个输入源(嵌套"while read"循环吗?) [英] Bash: Looping over multiple input sources (nesting "while read" loops?)

查看:250
本文介绍了Bash:循环多个输入源(嵌套"while read"循环吗?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a query.sh script which runs dig commands, performing a set of lookups from different DNS servers, which are currently given in a column in the single input file used (sites.txt).

我的目标是修改此脚本以使用不同的输入文件dns_servers.txt,以找到针对每个查询进行迭代的DNS服务器.

My goal is to modify this script to use a different input file, dns_servers.txt, to find the DNS servers to iterate through for each query.

我不清楚从哪里开始.为了能够安全嵌套while read循环,我需要做什么?

I'm not clear on where to start here. What do I need to do to be able to safely nest while read loops?

#!/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服务器,用于根据该主机名进行查找.

sites.txt

Current format has a hostname and a DNS server to use for lookups against that hostname.

www.google.com 8.8.4.4

目的是忽略DNS服务器所在的列,而使用dns_servers.txt的内容代替.

The intent is for the column with the DNS server to be ignored, and the contents of dns_servers.txt to be used instead.

10.1.1.1
12.104.1.232
...

推荐答案

忽略sites.txt文件中的任何其他列,并遍历dns_servers.txt的行,可能类似于以下内容:

Ignoring any additional column(s) in the sites.txt file, and iterating through the lines of dns_servers.txt, might look like the following:

#!/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),以使它们分开.
  • Pass the list of fields you want to parse as arguments to read. The underscore passed as second positional argument to the first read is the variable name to which the second column of site.txt is now being saved.
  • Nest your loops, since you want to read from the inner loop for every pass of the outer loop.
  • Use a different file descriptor (here, 3 and 4) for outer and inner loops to keep them separated.

顺便说一句,如果您的目标是bash(#!/bin/bash)而不是POSIX sh(#!/bin/sh),我可能会采取不同的做法.下面使用bash 4扩展名mapfile一次读取所有dns_servers.txt:

Incidentally, if you were targeting bash (#!/bin/bash) rather than POSIX sh (#!/bin/sh), I might do this differently. The below uses the bash 4 extension mapfile to read dns_servers.txt all at once:

#!/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读取的每个值重复使用该值列表.

Here, we read dns_servers.txt only once, and reuse that list of values for each value read from sites.txt.

如果您使用的是bash 3.x,则mapfile可以替换为循环:

If you're using bash 3.x, mapfile can be replaced with a loop:

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

这篇关于Bash:循环多个输入源(嵌套"while read"循环吗?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆