Bash:循环多个输入源(嵌套"while read"循环吗?) [英] Bash: Looping over multiple input sources (nesting "while read" loops?)
问题描述
我有一个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
的第二列保存到的变量名称. - 嵌套循环,因为您希望每次通过外部循环时都从内部循环中读取数据.
- 对于内部循环和内部循环,请使用不同的文件描述符(此处为
3
和4
),以使它们分开.
- Pass the list of fields you want to parse as arguments to
read
. The underscore passed as second positional argument to the firstread
is the variable name to which the second column ofsite.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
and4
) 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屋!