使用for循环解析txt文件时的进度指示器

使用for循环解析txt文件时的进度指示器

我正在尝试创建一个非常简单的脚本来测试 dns 服务器并将结果返回到 csv 文件中,它工作得很好,但是使用大型域源文件需要很长时间。

有没有办法使用 pv 或 awk 创建进度指示器?

#!/bin/bash
# File name of domain list: One FQDN per line in file.
domain_list='domains.txt'
#
# IP address of the nameserver used for lookups:
ns1_ip='1.1.1.1' # Cloudflare
ns2_ip='9.9.9.9' # Quad9
#
# Seconds to wait between lookups:
loop_wait='1'
#
echo "Domain name, $ns1_ip,$ns2_ip" > dns-test-results.csv;
for domain in `cat $domain_list`
do
    ip1=`dig @$ns1_ip +short $domain |tail -n1`; 
    ip2=`dig @$ns2_ip +short $domain |tail -n1`;
    echo -en "$domain,$ip1,$ip2\n" >> dns-test-results.csv;
# 
done;


答案1

您可以首先将项目存储在数组中以对它们进行计数,然后在每次循环迭代中打印已处理项目的数量和总数。

例如这样的事情:

items=( $(cat items.txt) )
i=0; for x in "${items[@]}"; do
    printf "\r%d/%d" "$(( i += 1 ))" "${#items[@]}";
    sleep 1  # do some actual work here
done
echo

但请注意,依赖于分词$(cat file...)有点问题,并且您最好使用readarray更安全地将每个输入文件读入数组元素:

readarray -t items < items.txt

答案2

与 ilkkachu 的建议类似,您可以使用 while 循环来阅读:

#!/bin/bash
# File name of domain list: One FQDN per line in file.
domain_list='domains.txt'
number=$( wc -l < "$domain_list")
#
# IP address of the nameserver used for lookups:
ns1_ip='1.1.1.1' # Cloudflare
ns2_ip='9.9.9.9' # Quad9
#
# Seconds to wait between lookups:
loop_wait='1'
#
echo "Domain name, $ns1_ip,$ns2_ip" > dns-test-results.csv;
count=0
while read -r domain
do
  (( count++ ))
  printf '\rProcessing domain %d of %d' "$count" "$number"
  ip1=$(dig @$ns1_ip +short $domain |tail -n1); 
  ip2=$(dig @$ns2_ip +short $domain |tail -n1);
  printf "%s,%s,%s\n" "$domain" "$ip1" "$ip2" >> dns-test-results.csv;
  sleep "$loop_wait"
# 
done < "$domain_list"
echo

上面的代码将打印当前正在查看的数字在Processing domain x of y哪里以及中的总行数。xy$domains_list

答案3

printf .每次检查记录时,您都可以在脚本中添加。并通过 pv 进行管道传输(假设domains.txt每个记录是行分隔的):

script.sh | pv -p -s "$(wc -l < domains.txt)" > /dev/null

但你可以做得更好。

相反echo -en "$domain,$ip1,$ip2\n" >> dns-test-results.csv;,你可以只拥有echo "$domain,$ip1,$ip2"。然后使用pv行模式并以更“关注点分离”的方式调用:

script.sh | pv -p -l -s "$(wc -l < domains.txt)" > dns-test-results.csv

答案4

您可以使用陷阱使 shell 定期打印进度信息。

#!/bin/bash

# child sends SIGUSR1 to the parent every $PERIOD seconds.

MAINPID=$BASHPID
PERIOD=3

pinger()  {
    (
    trap exit ERR
    while true
    do
        sleep $PERIOD
        kill -USR1 $MAINPID
    done
    ) &
}

# ====

# when main process receives SIGUSR1, print some progress info

trap progress SIGUSR1

progress() {
    printf "Progress: %d spins are spun\r" $COUNT
    return
}

# ====

# Start the pinger
pinger

# actual work goes here

for((COUNT=1; COUNT<300; COUNT++))
do
    sleep 0.100
done

exit

相关内容