Bash 스크립트 오류 [:! = : 단항 연산자가 필요합니다.


96

내 스크립트에서 첫 번째이자 유일한 인수가 -v와 같지만 선택적 인수인지 오류 확인을 시도하고 있습니다. if 문을 사용하지만 단항 연산자 예상 오류가 계속 발생합니다.

이것은 코드입니다.

if [ $1 != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

편집하다:

좀 더 구체적이어야합니다. 위 스크립트의이 부분은 선택적 인수를 확인한 다음 인수가 입력되지 않은 경우 나머지 프로그램을 실행해야합니다.

#!/bin/bash

if [ "$#" -gt "1" ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" = -v ]; then
   echo "`ps -ef | grep -v '\['`"
else
   echo "`ps -ef | grep '\[' | grep root`"
fi

... 그건 그렇고, 나는 당신이 원한다고 생각합니다 echo "usage: $0 [-v]"; $-현재 스크립트의 이름이 아닌 활성 쉘 옵션 플래그를 표시합니다.
Charles Duffy 2014 년

저는 그 부분이 맞습니다. 현재 스크립트의 이름을 보여주고 싶습니다.
user3380240

4
stackoverflow, 특히 bash 태그에 오신 것을 환영합니다! 이와 같은 많은 문제를 (항상 설명하지는 않지만) 지적 할 shellcheck 와 같은 유용한 도구 및 리소스에 대해서는 태그 위키 를 확인하십시오 .
다른 사람

@ user3380240 은 현재 스크립트의 이름 $-아닙니다 . $0이다.
Charles Duffy 2014 년

죄송합니다. 오타였습니다.
user3380240

답변:


189

인용 부호!

if [ "$1" != -v ]; then

그렇지 않으면 $1이 완전히 비어 있으면 테스트가 다음과 같이됩니다.

[ != -v ]

대신에

[ "" != -v ]

... !=단항 연산자가 아닙니다 (즉, 단일 인수 만 취할 수있는 연산자).


8
또는 이식성에 대해 걱정하지 않는다면 이중 괄호를 사용할 수 있습니다. 그 안에 변수 확장을 인용 할 필요가 없습니다. if [[ $1 != -v ]]; then
Mike Holt

@MikeHolt, 실제로-위의 질문에 대한 의견에서 그것을 언급합니다.
Charles Duffy 2014 년

경우 @DanielDinnyes, IFS=1다음, [ $# -eq 1 ]잘 작동하지 않습니다, 반면 [ "$#" -eq 1 ]동작합니다 심지어 다음과 같이 의도. 물론 병리학적인 경우이지만 선택권이 주어 졌을 때 소프트웨어가없는 소프트웨어를 작성하는 것이 좋습니다.
Charles Duffy

-2

또는 만연한 과잉처럼 보이지만 실제로는 단순합니다 ... 거의 모든 경우를 다루고 빈 문자열이나 단항 문제는 없습니다.

첫 번째 인수가 '-v'인 경우 조건부를 수행 ps -ef하고 다른 모든 경우에는 사용법을 던집니다.

#!/bin/sh
case $1 in
  '-v') if [ "$1" = -v ]; then
         echo "`ps -ef | grep -v '\['`"
        else
         echo "`ps -ef | grep '\[' | grep root`"
        fi;;
     *) echo "usage: $0 [-v]"
        exit 1;; #It is good practice to throw a code, hence allowing $? check
esac

'-v'인수가 어디에 있는지 신경 쓰지 않는다면 단순히 케이스를 루프 안에 놓으십시오. 모든 인수를 걷고 어디에서나 '-v'를 찾을 수 있습니다 (존재하는 경우). 이는 명령 줄 인수 순서가 중요하지 않음을 의미합니다. 제시된 바와 같이 변수 arg_match가 설정되어 있으므로 이는 단지 플래그 일뿐입니다. '-v'인수를 여러 번 사용할 수 있습니다. 다른 모든 '-v'발생은 쉽게 무시할 수 있습니다.

#!/bin/sh

usage ()
 {
  echo "usage: $0 [-v]"
  exit 1
 }

unset arg_match

for arg in $*
 do
  case $arg in
    '-v') if [ "$arg" = -v ]; then
           echo "`ps -ef | grep -v '\['`"
          else
           echo "`ps -ef | grep '\[' | grep root`"
          fi
          arg_match=1;; # this is set, but could increment.
       *) ;;
  esac
done

if [ ! $arg_match ]
 then
  usage
fi

그러나 인수가 여러 번 발생하도록 허용하는 것은 다음과 같은 상황에서 사용하기 편리합니다.

$ adduser -u:sam -s -f -u:bob -trace -verbose

우리는 인수의 순서를 신경 쓰지 않고 여러 개의 -u 인수를 허용합니다. 예, 다음을 허용하는 것도 간단한 문제입니다.

$ adduser -u sam -s -f -u bob -trace -verbose

$*이 컨텍스트에서 사용해서는 안됩니다. 항목을 문자열 분할 및 glob 확장 된 문자열로 연결합니다. 과 달리 "$@"항목은 정확한 원래 값으로 남습니다. 그리고 shellcheck.net 이 잡을 몇 가지 인용문을 놓치고 있습니다 (그 인용문이 중요한 이유를 설명하는 위키 페이지에 연결된 경고와 함께).
Charles Duffy

구체적인 예로, -U'Bob Barker'; for arg in $*로 볼 수 -UBobBarker별도의 항목으로; 반면 단일 문자열로 for item in "$@"표시 -UBob Barker됩니다.
Charles Duffy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.