내가 원하는 코드 조각은 다음과 같습니다.
루프를 5번 반복합니다.
각 반복에서 다음 줄을 가져와야 합니다. 해당
줄을 파일의 시작
부분에 추가합니다.
ping; 일부 문장을 인쇄하고 사용자에게 코드 진행 상황을 알립니다.
반복이 효과가 있었습니다.
sed 부분을 건너뛰면 모든 것이 잘 작동하지만 동일한 대상에 대해 ping을 5번 실행합니다.
호스트.txt 파일의 각 줄에는 핑하려는 IP 주소가 있습니다.
for ((i>=1;i<=5;i++))
do
sed -n "$i p" hosts.txt | read output
touch "$output.txt"
date >> "$output.txt"
printf "\nComeçando o teste de $output."
printf "\nTeste em andamento."
ping -c 10 -i 1 "$output" >> "$output.txt"
done
문제는 sed 구문에 문제가 있다는 것입니다. bash를 직접 시도하면 sed -n 1p hosts
첫 번째 줄이 표시됩니다. 그러나 숫자가 $i여야 하기 때문에 p 앞에 $i를 넣으면 bash는 변수 i와 그 뒤에 인수 p를 더하는 대신 ip를 변수로 해석합니다.
어떻게 하면 이 동작을 수정하고 더 이상 문제를 일으키지 않을 수 있나요?
답변1
나는 당신이 bash를 사용하고 있다고 가정하고 있으므로 이것이 더 잘 작동할 것입니다:
for ((i=1;i<=5;i++))
do
sed -n "$i p" hosts.txt | (
read output
touch "$output.txt"
date >> "$output.txt"
printf "\nComeçando o teste de $output."
printf "\nTeste em andamento."
ping -c 10 -i 1 "$output" >> "$output.txt"
)
done
문제는 bash
대부분의 외부 쉘 인터프리터와 마찬가지로 ksh
모든 파이프 구성 요소가 하위 쉘에 배치되므로 output
변수가 설정되자마자 손실된다는 것입니다.
또한 변수가 초기화되지 않아 for
정의되지 않은 동작이 발생한 루프를 수정했습니다 .i
답변2
보시다시피 문제는 및 둘 다 유효한 변수 이름이라는 i
것 입니다. 따라서 문자 뒤에 오는 값을 ip
사용하려면 중괄호를 사용하여 변수 이름이 시작하고 끝나는 위치를 명확하게 구분할 수 있습니다.$i
p
sed -n "${i}p" hosts.txt | read output
답변3
약간 더 간단한 해결책은 다음과 같습니다.
for ((i=1; i<=5; i++))
do
read output
date >> "$output.txt"
printf "\nComeçando o teste de %s." "$output"
printf "\nTeste em andamento."
ping -c 10 -i 1 "$output" >> "$output.txt"
done < hosts.txt
< hosts.txt
마지막 줄 끝에 있는 을 참고하세요 done
. 이렇게 하면 해당 줄이 한 번 열리고 hosts.txt
그 안의 처음 5줄만 읽혀집니다. don_crissti가 언급했듯이 루프에서 이 작업을 수행한다는 것은 파일을 5번 sed … hosts.txt | read output
읽는다는 의미입니다 . 파이프라인이 아닌 루프의 나머지 부분과 평행하기 hosts.txt
때문에 read output
루프의 나머지 코드는 output
파일에서 읽은 값에 액세스할 수 있습니다. 또한 (지적한 것처럼) touch
;command >> file
file
아직 존재하지 않는 경우.
파일 중 하나가 hostname.txt
이미 존재하는 경우 이 코드는 해당 파일에 새 정보를 추가합니다. 이전 데이터를 버리고 처음부터 시작하려면 date > "$output.txt"
대신 을 수행하십시오 date >> "$output.txt"
.
알 수 없는 데이터를 에 직접 전달할 때는 주의하세요 printf
. 드물게 "호스트 이름" 중 하나가 포함되면 %
코드에서 해당 이름이 왜곡될 수 있습니다. 외부 데이터를 %s
(인쇄 문자열) 에 전달하는 것이 좋습니다 .
파일의 처음 다섯 줄만 읽고 hosts.txt
중지할지, 아니면 전체 파일을 읽고 싶었는데 우연히 그 길이가 다섯 줄인지는 말하지 않았습니다. 전체 파일을 읽으려면 다음을 수행하십시오.
while read output
do
date >> "$output.txt"
printf "\nComeçando o teste de %s." "$output"
printf "\nTeste em andamento."
ping -c 10 -i 1 "$output" >> "$output.txt"
done < hosts.txt
파일 끝에 도달하면 명령문이 read output
실패하고 루프가 종료됩니다.