공백 없이 출력 문자열에서 변수 이름 분리

공백 없이 출력 문자열에서 변수 이름 분리

내가 원하는 코드 조각은 다음과 같습니다.

루프를 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.txtread output루프의 나머지 부분(파이프라인이 아님)과 평행하므로 루프의 나머지 코드는 output파일에서 읽은 값에 액세스할 수 있습니다. 또한 (지정한 것처럼) 필요하지 않습니다 touch. 만들 것이다command>>filefile이미 존재하지 않는 경우.

파일 중 하나가 이미 존재하는 경우 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실패하고 루프가 종료됩니다.

관련 정보