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

트랩을 사용하여 쉘이 주기적으로 진행 정보를 인쇄하도록 할 수 있습니다.

#!/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

관련 정보