Bash 스크립트에서 "test $2 &&"는 무엇을 의미합니까?

Bash 스크립트에서 "test $2 &&"는 무엇을 의미합니까?

다음 코드가 포함된 bash 스크립트를 보고 있습니다.

#!/bin/sh

set -e # Exit if any command fails

# If multiple args given run this script once for each arg
test $2 && {
  for arg in $@
    do $0 $arg
  done
  exit
}
.
.
.

주석에서 언급했듯이 목적은 "인수가 여러 개인 경우 각 인수에 대해 스크립트를 실행합니다"입니다. 이를 테스트하기 위한 실행기 코드가 있습니다.

# install-unit
# If multiple args given run this script once for each arg
test $2 && {
  echo "\$0: $0"
  echo "\$1: $1"
  echo "\$2: $2"
  echo "test \$2 && is true"
}

test $2 && {
# note this is just a regular bash for loop
# http://goo.gl/ZHpBvT
  for arg in $@
    do $0 $arg
  done
  exit
}

echo "running: $1"

다음과 같은 결과를 제공합니다.

sh ❯ ./multiple-run.sh cats and dogs and stuff
$0: ./multiple-run.sh
$1: cats
$2: and
test $2 && is true
running: cats
running: and
running: dogs
running: and
running: stuff
sh ❯ ./multiple-run.sh cats
running: cats

test $2 && {}누군가가 그 부분과 exit내장 쉘을 풀 수 있기를 바랍니다 . 처음에는 test $2인수가 더 있는지 확인하는 줄 알았는데 , 그럴 수도 있겠네요. 그런데 "and"로 구분된 표현식이 두 개 있는 것 같아서 이상하게 보이고, 내장 함수가 정확히 무슨 일을 하는 &&지도 헷갈립니다. exit.

예제와 문서 참조가 포함된 간단한 영어 설명을 부탁드립니다 :)

감사해요!

편집자: Stéphane Chazelas에게 감사드립니다. for 루프 구문의 변경 사항으로 인해 혼란스러워하는 사람은 이 문서의 3번 항목을 확인하세요.괴짜 물건기사. 결론적으로:

echo "positional parameters"
for arg do
  echo "$arg"
done

echo "\nin keyword"
for arg in "$@"
  do echo "$arg"
done

우리에게 줘:

❯ ./for-loop-positional.sh cats and dogs          
positional parameters
cats
and
dogs

in keyword
cats
and
dogs

답변1

이것은 잘못된 작성 방법입니다.

#!/bin/sh -

set -e # Exit if any command fails

# If multiple args given run this script once for each arg
if [ "$#" -gt 1 ]; then
  for arg do
    "$0" "$arg"
  done
  exit
fi

작성자가 원하는 것은 두 번째 매개변수가 비어 있지 않은 문자열인지 확인하는 것이라고 생각합니다. 이는 두 번째 매개변수가 전달될 수 있지만 빈 문자열이기 때문에 매개변수가 2개 이상 있는지 확인하는 것과 다릅니다.

test somestring

짧은 형식

test -n somestring

somestring빈 문자열이 아닌 경우 true를 반환합니다. ( test ''false를 반환하고 test anythingelsetrue를 반환합니다(그러나 test -t일부 쉘에서는 stdout이 터미널인지 확인하기 위해 검사됩니다)).

그러나 작성자는 변수 주변의 따옴표(실제로는 모든 변수)를 잊어버렸습니다. 이것이 의미하는 바는 $2분할+글로브 연산자에 따라 다릅니다. 따라서 $2문자 $IFS(기본적으로 공백, 탭, 줄 바꿈) 또는 전역 문자( *, ?, )가 포함되어 있으면 [...]제대로 작동하지 않습니다 .

비어 있는 경우 $2(예: 2개 미만의 인수가 전달되거나 두 번째 인수가 비어 있는 경우) 대신 , test $2가 됩니다 . 인수를 전혀 받지 않습니다(비어 있거나 그렇지 않은 경우).testtest ''test

다행히 test이 경우 어떤 매개변수도 false를 반환하지 않습니다. true를 반환하는 것보다 약간 낫기 test -n $2때문에(이것은 test -n와 동일 해지기 때문에 test -n -n) 일부 경우에는 이 코드가 작동하는 것 같습니다.

요약하다:

  • 2개 이상의 매개변수가 전달되는지 테스트합니다.

    [ "$#" -gt 1 ]
    

    또는

    [ "$#" -ge 2 ]
    
  • 변수가 비어 있지 않은지 테스트합니다.

    [ -n "$var" ]
    [ "$var" != '' ]
    [ "$var" ]
    

    이들 모두는 POSIX 구현에서 신뢰할 수 있지만 [아주 오래된 시스템을 처리해야 한다면 다음을 사용해야 할 수도 있습니다.

    [ '' != "$var" ]
    

    반면 , , ...와 [같은 값을 구현하는 경우 에는$var=-t(

  • 변수가 정의되었는지 테스트합니다(스크립트에 두 번째 인수가 전달되었는지 테스트하는 데 사용할 수 있지만 $#읽기 쉽고 사용하기 더 관용적입니다).

    [ "${var+defined}" = defined ]
    

(또는 그에 상응하는 . 명령 에 별칭을 test사용하는 것이 더 일반적입니다 .)[test


cmd1 && cmd2이제 와 의 차이점에 대해 이야기해 보세요 if cmd1; then cmd2; fi.

cmd2둘 다 cmd1성공할 때만 실행됩니다. 이 경우의 차이점은 전체 명령 목록의 종료 상태가 &&이 경우 실행된 마지막 명령의 종료 상태가 된다는 것입니다.실패하다코드는 cmd1true를 반환하지 않지만(여기서는 아무 문제도 발생하지 않지만 set -e)), 이 경우 실행되지 않으면 0(성공)이 if됩니다 .cmd2cmd2

그래서 다음 cmd1과 같이 사용됩니다.상황(실패로 간주되지 않는 경우질문), 일반적으로 이를 사용하는 것이 가장 좋습니다. if특히 스크립트의 종료 상태를 정의하므로 스크립트에서 마지막으로 수행하는 작업인 경우 더욱 그렇습니다. 또한 코드가 더 명확해집니다.

cmd1 && cmd2형식은 다음과 같이 더 일반적으로 사용됩니다.상황그들은 스스로 다음을 좋아합니다:

if cmd1 && cmd2; then...
while cmd1 && cmd2; do...

이는 이 두 명령의 종료 상태에 관심이 있는 경우입니다.

답변2

test $2 && some_command이는 두 가지 명령으로 구성됩니다.

  • test $2$2두 번째 인수( )의 확장된 문자열의 길이가 0이 아닌지 확인합니다 . 즉, test -n $2( [ -n $2 ])을 확인해야 합니다. 공백이 있는 값 은 주위에 따옴표를 사용하지 않으므로 차단됩니다 $2. 이것을 test사용해야합니다 test "$2".

  • &&단락 평가 연산자입니다. 즉, &&이전 명령이 성공한 경우에만 다음 명령이 실행됩니다(즉, 종료 코드가 0임). 따라서 위의 예에서는 성공하는 some_command경우에만 실행됩니다 (즉, 문자열이 test $2길이가 아닌 경우). 그런 다음 some_command실행됩니다.

관련 정보