쉘 스크립트 "if" 문에서 참조된 변수의 차이점은 무엇입니까?

쉘 스크립트 "if" 문에서 참조된 변수의 차이점은 무엇입니까?

이 두 Bash if 문의 차이점은 무엇입니까? 예를 들어

if [ "$FOO" = "true" ]; then

비교됨

if [ $FOO = "true" ]; then

차이점이 뭐야? 이 두 진술은 동일한 효과를 갖는 것 같습니다.

답변1

값이 $FOO와일드카드 문자를 포함하지 않는 단일 단어 인 경우 둘은 동일합니다 \[*?.

$FOO따옴표가 없는 버전 은 할당되지 않았거나 비어 있거나 두 개 이상의 단어가 있는 경우 (예: 공백 또는 가 포함된 경우) $IFS구문 오류입니다 . 올바른 단어 순서(예: )인 경우 0 -eq 0 -o false결과는 임의적일 수 있습니다. 따라서 쉘 스크립트에서는 항상 변수를 인용하는 것이 가장 좋습니다.

그런데 "true"인용은 필요하지 않습니다.

답변2

이로 인해 발생할 수 있는 문제를 설명하기 위해 다음과 같은 몇 가지 예가 있습니다.

다음과 같은 두 가지 변수가 있다고 가정합니다.

FOO="some value"
BAR="some value"

이제 정확히 동일한 문자열/값을 보유하는 두 개의 변수가 있습니다. 귀하의 경우 결과를 테스트하기 위해 if 문을 만드는 경우:

if [ $FOO = "$BAR" ]; then echo "match"; else echo "no match"; fi

이 시점에서 bash: [: too many arguments따옴표 없이 .$FOO에는 세 개의 값이 포함됩니다. 즉, '[ , some , value'test [키워드는 첫 번째 또는 두 번째 인수가 연산자일 것으로 예상하기 때문에 무엇을 해야할지 모릅니다.

if"$FOO"를 참조할 때 토큰화가 발생하지 않은 올바른 값을 보도록 명시적으로 지시됩니다 .

다른 예시:

my_file="A random file.txt"
  • 이렇게 하면 rm $my_file"A" "random" "file.txt"를 삭제하여 3개의 파일이 됩니다.
  • 이렇게 하면 rm "$my_file"파일을 생성하는 "임의의 file.txt"가 삭제됩니다.

이러한 예를 들어 여러분을 혼동하지 않았으면 좋겠습니다.

답변3

여기서 중요한 것은 if명령문 내의 참조가 아니라 모든 명령의 매개변수 내의 참조이며, 특정 경우에는 명령 입니다 [.

[명령은 다른 명령과 유사하며(비록 대부분의 Bourne 유사 쉘에 내장되어 있음) 명령문 외부는 물론 명령문의 if, then, elif, else부분 내에서 사용할 수 있습니다 .if...fiif...fi

zsh이외 의 Bourne형 쉘에는분할+전역운영자.

$FOO는 복잡한 규칙을 사용하여 문자를 기준으로 분할되며 $IFS결과 단어는 파일 이름 생성의 영향을 받습니다. [이는 정확히 하나의 인수를 예상하지만 명령에서 가변 개수의 인수를 생성합니다.

따라서 명령에 대한 인수와 마찬가지로 $FOO해당 내용이 인수로 전달되도록 따옴표로 묶어야 합니다.

[명령 중 하나입니다비판적인변수를 인용하는 것을 잊지 마십시오. 그렇게 하지 않으면 [많은 구현에서 임의의 명령 주입이 됩니다(변수의 내용이 공격자의 제어 하에 들어갈 가능성이 있는 경우).

여기에는 , 및 파생 항목(및 /emulation에 있는 경우)에 대한 내장 유틸리티 [뿐만 아니라 내장 래퍼 스크립트로 구현되는 Solaris( , ... )와 같은 시스템용 독립 실행형 유틸리티도 포함됩니다.bashksh88ksh93pdkshzshshksh[/bin/[/usr/xpg4/bin/[ksh[

이러한 [구현(예: 셸의 모든 내장 명령)은 경우에 따라 산술 표현식을 해석하거나 변수 이름에 대해 연산을 수행하여 궁극적으로 코드를 실행할 수 있습니다.

예를 들어, bash셸(GNU 프로젝트의 셸 및 sh일부 시스템의 구현)에서 기본값은 다음과 같습니다 $IFS.

bash-5.0$ FOO='-v x[$(reboot)] -o true'
bash-5.0$ if [ $FOO = "true" ]; then echo yes; fi
System rebooting now!
yes

따옴표가 없고 $IFS기본적으로 SPC 문자가 포함되어 있기 때문에 , , $FOO로 나누어져 있습니다 . 이 중 두 번째에만 전역 연산자( )가 포함되어 있습니다. 내 경우에는 어떤 파일과도 일치하지 않았으므로(예: 현재 디렉토리에 파일이 있으면 상황이 달라질 수 있음) 그대로 두었습니다(Bourne과 같은 쉘의 또 다른 특성, 대부분의 다른 쉘은 전역에 대해 불평합니다. 불일치).-vx[$(reboot)]-otrue[...]xo

[따라서 배열이 $xindex 로 설정되어 해당 산술 표현식 평가의 일부로 실행되는지 또는 $(reboot)( )가 같으면 출력이 되는지 묻는 메시지가 표시됩니다 .reboot-otruetrueyes

추가 자료:

답변4

이 특정한 경우에는 차이가 없습니다.

하지만 $FOO공백이나 특수 문자가 포함되어 있으면 문제가 발생합니다.

"$FOO"경우 일치로 인해 공간 문제가 발생하지 않도록 총 변수를 사용합니다.

그러나 $FOOand를 사용할 때 특별한 상황이 있는 경우 if 문에 영향을 미칩니다.

관련 정보