일부 조건에 따라 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
더 좋습니다 :2
3
254
255
case
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]
- AND 또는 목록:
- 복합 명령:
- 그룹화 명령:
( 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
에서 사용 됩니다 .case
if
while
until
{ compound_list; }
명령의 마지막 명령이 compound_list
닫는 대괄호와 같은 줄에 있는 경우에도 }
세미콜론이 필요합니다 .