이 bash 조건 검사는 [[ -n .. ]]에서는 작동하지만 [ -n .. ]에서는 작동하지 않는 이유는 무엇입니까? [복사]

이 bash 조건 검사는 [[ -n .. ]]에서는 작동하지만 [ -n .. ]에서는 작동하지 않는 이유는 무엇입니까? [복사]

[ -n $value ]bash 조건식에 사용되는 길이가 0인 문자열을 감지할 수 없는 스크립트가 있습니다 .

#!/usr/bin/env bash

value=""
if [ -n $value ]
then
    echo "value is non-zero"
fi

결과

0이 아닌 값

[[ -n $value ]]즉, 다음을 사용하면 작동합니다.

#!/usr/bin/env bash

value=""
if [[ -n $value ]]
then
    echo "value is non-zero"
fi

을 사용하면 [[예상된 출력이 생성되지 않습니다. 매뉴얼 페이지에서:

   [[ expression ]]
      Return a status of 0 or 1 depending on the evaluation of the conditional expression expression.  Expressions are composed of the pri‐
      maries described below under CONDITIONAL EXPRESSIONS.  Word splitting and pathname expansion are not performed on the  words  between
      the  [[  and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution,
      and quote removal are performed.  Conditional operators such as -f must be unquoted to be recognized as primaries.

나는 이 행동을 설명할 수 없다. 길이가 0인 문자열이 감지되었으나 감지되지 않는
이유는 무엇입니까 ?[[[

답변1

이는 [[다음과 같은 이유 때문입니다.표현하다, [그리고논쟁그것은 다음과 같이 번역됩니다표현하다.

[[구문입니다 - 그렇지 않습니다내장 명령있는 그대로 [지만[[복합 명령그것보다 더 유사 {하거나 더 유사합니다 .([

어쨌든 [[파싱되었기 때문에옆에 $expansions, null 확장과 누락된 피연산자의 차이점을 이해하는 것은 어렵지 않습니다.

[그러나 이것은 일상적인 실행입니다.뒤쪽에모든 명령줄 확장이 발생했으며 표현식을 평가할 때 $null_expansion아무것도 확장되지 않았으므로 수신되는 것은 [ -n ],허용되지 않음유효한 표현입니다. 여기 [와 같이 비어 있지 않은 단일 인수의 경우 true가 반환되도록 지정 하지만-n스펙이 너무 똑같네요계속해……

이 두 명령은 다음과 같습니다.

  test "$1"
  test ! "$1"

일부 과거 시스템에서는 안정적으로 작동하지 않습니다. 이러한 문자열 표현식을 사용하고 이를 이나 알려진 단항 기본 표현식 $1으로 확장하면 예기치 않은 결과가 발생할 수 있습니다.!((예를 들어 -n). 더 나은 구성은 다음과 같습니다.

  test -n "$1"
  test -z "$1" 

두 가지 형태 모두 장점과 단점이 있습니다. [표현식을 구성할 수 있습니다.밖의확장 등:

[ "-${z:-n}" "$var" ]

...테스트를 빌드하는 데 완벽하게 유효한 방법일 수 있지만 다음에서는 작동하지 않습니다.

[[ "-${z:-n}" "$var" ]]

...이건 의미 없는 명령이군요. 차이점은 전적으로 테스트가 실행되는 명령줄 구문 분석 지점 때문입니다.

답변2

변수를 큰따옴표로 묶을 필요는 없지만 [[ ]]따옴표로 묶어야 합니다 [ ].

따옴표가 없으면 $value빈 문자열과 [ -n $value ]동일합니다 [ "-n" ]. "-n"문자열 테스트이고 비어 있지 않은 것으로 평가되므로 true이므로 테스트가 성공합니다.

(왜요? -n STRING와 aka는 STRING동일하기 때문입니다. 둘 다 비어 있지 않은 문자열에 대한 테스트입니다.)[test

추가 실험에 따르면 이는 파일 연산자를 포함한 모든 단일 피연산자 테스트에 해당되는 것으로 나타났습니다. 피연산자가 없으면 [ ]단일 인수가 문자열 테스트로 처리됩니다. 이것이 스크립트 작성자가 수십 년 동안 의존했던 역사적 사실이 아니었다면 아마도 버그로 간주되어 수정되었을 것이며 이를 변경하면 수많은 기존 스크립트가 중단될 것입니다.

인용된 [ -n "$value" ]AND는 정확히 동일하므로 [ -n "" ]테스트가 실패합니다.

[[ ... ]]변수에 대한 참조에 대한 더 관대함 - 참조는 선택 사항이며 따옴표가 있든 없든 동일하게 작동합니다.

관련 정보