"while" 루프에서 변수를 설정하기 위해 "읽기 변수"를 사용할 때는 전역 변수인 반면, "읽는 동안 변수"를 사용하여 변수를 설정할 때는 로컬 변수인 이유는 무엇입니까?

"while" 루프에서 변수를 설정하기 위해 "읽기 변수"를 사용할 때는 전역 변수인 반면, "읽는 동안 변수"를 사용하여 변수를 설정할 때는 로컬 변수인 이유는 무엇입니까?
unset myVariable i;
while [ -z "$i" ]; do
    read myVariable;
    echo "myVariable : '$myVariable'";
    i=foo;
done;
echo "myVariable : '$myVariable'"

( unset명령 재생을 허용합니다)

아무 키나 + Enter를 누르면 다음이 표시됩니다.

myVariable : '[what you typed]'
myVariable : '[what you typed]'

값이 루프 myVariable외부에 존재합니다 . while지금 시도해보세요:

tmpFile=$(mktemp);
echo -e 'foo\nbar\nbaz' >> "$tmpFile"
while read myVariable; do
    otherVariable=whatever; 
    echo "myVariable : '$myVariable', otherVariable : '$otherVariable'";
done < "$tmpFile";
echo "myVariable : '$myVariable', otherVariable : '$otherVariable'";
rm "$tmpFile"

당신은 얻을 것이다:

myVariable : 'foo', otherVariable : 'whatever'
myVariable : 'bar', otherVariable : 'whatever'
myVariable : 'baz', otherVariable : 'whatever'
myVariable : '', otherVariable : 'whatever'

myVariable루프를 벗어나면 값이 손실됩니다.

왜 다른 행동을 하는가? 내가 모르는 범위 지정 요령이 있나요?

참고: GNU bash 버전 4.4.12(1) 릴리스(x86_64-pc-linux-gnu) 실행

답변1

while read myVariable; do

myVariable루프를 벗어나면 값이 손실됩니다.

아니요, myVariable지난 번에 얻은 값이 있습니다 read. 스크립트는 마지막 개행 문자 다음 위치에 도달할 때까지 파일에서 읽습니다. 그 후 최종 read호출은 파일에서 아무것도 가져오지 않고 myVariable그에 따라 빈 문자열로 설정되며 구분 기호(개행)가 표시되지 않기 때문에 오류 값으로 종료됩니다. 그런 다음 사이클이 종료됩니다.

read마지막 줄 바꿈 뒤에 불완전한 줄이 있으면 끝에서 null이 아닌 값을 얻을 수 있습니다.

$ printf 'abc\ndef\nxxx' | 
    { while read a; do echo "got: $a"; done; echo "end: $a"; } 
got: abc
got: def
end: xxx

또는 while read a || [ "$a" ]; do ...루프 본문의 마지막 줄 조각을 처리하는 데 사용됩니다.

답변2

while 루프에 파이프를 연결하고 있기 때문에 while 루프를 실행하기 위한 하위 쉘이 생성됩니다. 이제 이 하위 프로세스에는 자체 환경 복사본이 있으며 UNIX 프로세스와 마찬가지로 어떤 변수도 상위 프로세스에 다시 전달할 수 없습니다.

이 경우 done < "$tmpFile"리디렉션은 bash가 하위 쉘(파이프용)을 생성하도록 강제합니다.

에서 인용bash 변수 범위스택 오버플로에.

답변3

두 번째 예에서는 while리디렉션된 입력이 포함된 루프를 사용합니다.

이는 using을 읽고 < "$tmpFile"많은 쉘이 이 경우에 대한 하위 쉘을 생성합니다. 를 사용하여 이 스크립트를 실행해 볼 수 있습니다 ksh93. ksh93이 경우 하위 쉘이 생성되지 않습니다.

특정 경우에는 이유가 완전히 다릅니다.

  • 첫 번째 예에서는 입력에서 한 줄을 읽습니다.

  • 두 번째 예에서는 EOF도달할 때까지 읽습니다.

명령 read은 입력을 읽은 다음 입력을 문자로 분할한 IFS다음 단어를 변수 인수에 할당합니다 read.

명령 인수로 변수보다 단어가 더 많은 경우 read마지막 변수는 나머지 단어를 연결합니다.

변수보다 단어 수가 적은 경우 다른 변수에는 null 값이 할당됩니다.

을 클릭했기 때문에 EOF단어를 읽지 않고 대신 하나 이상의 변수를 인수로 전달했습니다 read. 이로 인해 모든 변수에 null 값이 할당됩니다.

따라서 예상치 못한 일이 발생합니다. EOF이로 인해 while루프가 종료되고 echo루프 내부에 명령이 표시되지 않지만 이 경우 while루프 다음의 최종 명령만 표시됩니다.echowhileEOF

이제 이 final은 echohit에서 지워진 변수의 내용을 인쇄합니다 EOF.

관련 정보