쉘 스크립트에서 함수 호출

쉘 스크립트에서 함수 호출

일부 조건에 따라 0 또는 1을 반환하는 간단한 함수를 셸에 작성했습니다. 함수 이름을 foo로 지정하겠습니다.

foo(){

...

...

}

이제 아래와 같이 if 조건에서 foo를 호출하려고 합니다.

if ( foo $1 )

...

..

잘 작동합니다. 하지만 다음 방법을 사용하여 호출하면 오류가 발생합니다.

if [ foo $1 ]

...

...

"단항 연산자 예상" 오류가 발생하는 이유는 무엇입니까?

답변1

당신이 사용할 때:

if ( foo $1 )

서브 foo $1셸에서 실행하고 if종료 상태에 따라 작동합니다.

당신이 사용할 때:

if [ foo $1 ]

쉘을 사용하려고합니다 test.부자유효한 테스트 연산자가 아닙니다. 유효한 테스트 연산자를 찾을 수 있습니다여기.


귀하의 질문과 반드시 ​​관련이 있는 것은 아니지만 특히 쉘 테스트 대괄호 내에서 항상 변수를 인용해야 합니다. 무언가가 존재하는 한 쉘 테스트는 성공합니다. 따라서 유효한 테스트 연산자를 사용해도 원치 않는 결과가 나타날 수 있습니다.

$ unset var
$ [ -n $var ] && echo yes
yes
$ [ -n "$var" ] && echo yes
$ [ -n "" ] && echo yes
$ [ -n ] && echo yes
yes
$ [ foo ] && echo yes
yes
$ [ foo bar ] && echo yes
-bash: [: foo: unary operator expected

쉘 테스트에서 단일 문자열의 존재는 두 개 이상의 문자열이 존재하고 문자열 중 하나가 유효한 테스트 연산자인 경우 true로 평가됩니다.

답변2

if명령문은 명령의 종료 상태를 처리합니다. 함수는 return상태로 종료되거나 문자열을 에코해야 합니다. 귀하의 목적에는 return더 적절해 보입니다. 함수가 성공적으로 완료되면 0을 반환하고, 오류가 발생하면 다른 값을 반환합니다. 예:

$ foo(){ [ -e '/etc/passwd' ] && return 0;  }
$ if foo; then echo "/etc/passwd exists"; fi
/etc/passwd exists

실제로 와 는 동일한 명령이고 오류 발생 여부를 나타내기 위해 0 또는 0이 아닌 종료 상태를 반환하기 때문에 과 가 if [ ... ]; then...정확히 동일한 것을 자주 볼 수 있다는 점에 유의해야 합니다.if test ...; then...[test

답변3

다른 사용자가 말한 것 외에도 if복합 명령의 실제 구문은 다음과 같습니다.

if compound_list
then compound_list
[elif compound_list
then compound_list]...
[else compound_list]
fi

기본적으로 은 compound_list여러 명령의 목록입니다. if첫 번째 명령 다음에 나오는 마지막 명령의 종료 코드를 확인하여 COMPOUND_LIST실행할 항목( , 또는 중 하나 then ...)을 결정합니다.elif ...; then ...else ...

즉, 다음과 같이 다시 작성할 수 있습니다.

if foo "$1"; then
  # Code to execute if foo returns 0
else
  # Code to execute if foo returns 1
fi

다음 을 사용 하는 것이 foo더 좋습니다 :23254255case

foo "$1"

case "$?" in
  0) # Code to execute if foo returns 0 ;;
  1) # Code to execute if foo returns 1 ;;
  2) # Code to execute if foo returns 2 ;;
  3) # Code to execute if foo returns 3 ;;
  ...
  254) # Code to execute if foo returns 254 ;;
  255) # Code to execute if foo returns 255 ;;
esac

편집 1

구문에서 "$1"을 정의한 후에 ";"이 있습니까?

예, Kusalananda가 말했듯이 명령 구분 기호로 사용됩니다.

POSIX 정의다음 명령:

  • 간단한 명령:[assignments] program [arguments] [redirections]
  • 관로:[!] command [pipe_operator command]...
  • 목록:
    • AND 또는 목록:pipeline [and-or_list_operator pipeline]...
    • 화합물 목록:and-or_list [compound_list_operator and-or_list]
  • 복합 명령:
    • 그룹화 명령:
      • ( compound_list )
      • { compound_list; }
    • 을 위한:for name [in words]; do compound_list; done
    • 사례:case word in [[(] patterns ) compound_list ;;]... esac
    • 만약에:if compound_list; then compound_list; [elif compound_list; then compound_list;]... [else compound_list;] fi
    • 하지만:while compound_list; do compound_list; done
    • 까지:until compound_list; do compound_list; done
  • 기능 정의 명령:name() compound_command [redirections]

A는 compound_list_operator세미콜론이나 개행 문자일 수 있으며 // compound_list컨텍스트 for에서 사용 됩니다 .caseifwhileuntil

{ compound_list; }명령의 마지막 명령이 compound_list닫는 대괄호와 같은 줄에 있는 경우에도 }세미콜론이 필요합니다 .

관련 정보