Bash 스크립트에 전달 된 인수 수 확인


727

필요한 인수 개수가 충족되지 않으면 Bash 스크립트에서 오류 메시지를 인쇄하고 싶습니다.

다음 코드를 시도했습니다.

#!/bin/bash
echo Script name: $0
echo $# arguments 
if [$# -ne 1]; 
    then echo "illegal number of parameters"
fi

알 수없는 이유로 다음과 같은 오류가 발생했습니다.

test: line 4: [2: command not found

내가 무엇을 잘못하고 있지?


54
스크립트 이름을 지정하지 않아야합니다 test. 이것이 표준 유닉스 명령의 이름입니다.
Barmar

20
bash의 if 문에서 항상 '['( '[[') 또는 '('( '((')) 주위에 공백을 사용하십시오.
zoska

5
@zoska 주석에 추가하려면 [명령 앞에 구현되었으므로 'which ['를 시도하십시오. 전에 공백이 필요합니다.
Daniel Da Cunha

1
: 더 나은 예는 링크 아래에 기재되어 있습니다 stackoverflow.com/questions/4341630/...
라마 크리슈나

3
@ Barmar test는 PATH에없는 한 확실하게 이름을 지정 합니까?
user253751

답변:


1099

다른 간단한 명령처럼 [ ... ]또는 test인수 사이에 공백이 필요합니다.

if [ "$#" -ne 1 ]; then
    echo "Illegal number of parameters"
fi

또는

if test "$#" -ne 1; then
    echo "Illegal number of parameters"
fi

제안

Bash에서는 [[ ]]표현식의 일부가 아닌 한 따옴표가 필요하지 않을 수있는 변수로 단어 분할 및 경로 이름 확장을 수행하지 않으므로 대신 사용하는 것이 좋습니다.

[[ $# -ne 1 ]]

또한 인용되지 않은 조건 그룹화, 패턴 일치 (와 확장 패턴 일치 extglob) 및 정규식 일치 와 같은 다른 기능도 있습니다 .

다음 예제는 인수가 유효한지 확인합니다. 하나 또는 두 개의 인수를 허용합니다.

[[ ($# -eq 1 || ($# -eq 2 && $2 == <glob pattern>)) && $1 =~ <regex pattern> ]]

순수한 산술 표현식의 경우, 사용하는 (( ))일부 여전히 더 좋을 수 있지만, 그들은 여전히 가능 [[ ]]처럼 그 산술 연산자와 -eq, -ne, -lt, -le, -gt, 또는 -ge단일 문자열 인수로 식을 배치하여 :

A=1
[[ 'A + 1' -eq 2 ]] && echo true  ## Prints true.

다른 기능과 결합 해야하는 경우 유용합니다 [[ ]].

스크립트 종료

유효하지 않은 매개 변수가 전달 될 때 스크립트를 종료하는 것도 논리적입니다. 이것은 이미에서 제안 된 의견 으로 ekangas 하지만 누군가가 그것을 가지고이 답변을 편집 -1나뿐만 아니라 바로 그것을 할 수 있도록, 같은 반환 값.

-1그러나 Bash가 주장으로 받아 들여지 exit는 것은 명시 적으로 문서화되어 있지 않으며 일반적인 제안으로 사용될 권리가 아닙니다. 64이 정의 이후 가장 공식적인 값도 sysexits.h와 함께 #define EX_USAGE 64 /* command line usage error */. 대부분의 도구 는 잘못된 인수를 ls반환 2합니다. 나는 또한 2스크립트 로 돌아 왔지만 최근에는 더 이상 걱정하지 않고 1모든 오류에 사용 되었습니다. 그러나 2가장 일반적이며 아마도 OS별로 다르기 때문에 여기에 배치합시다 .

if [[ $# -ne 1 ]]; then
    echo "Illegal number of parameters"
    exit 2
fi

참고 문헌


2
OP : [다른 명령 일뿐 which [입니다.
레오

5
@Leo Commands는 내장 될 수 있지만 불가능합니다. bash에서는 [내장이며 [[키워드입니다. 일부 오래된 껍질에서는 [내장되어 있지 않습니다. 명령 좋아 [대부분의 시스템에서 외부 명령과 자연이 공존을하지만, 내부 명령으로 우회하면 않는 한 쉘에 의해 우선 순위 commandexec. 쉘의 문서가 어떻게 평가되는지 확인하십시오. 차이점과 각 쉘에서 서로 다르게 작동하는 방식에 유의하십시오.
konsolebox 2016

77

숫자를 다루는 경우 산술 표현식 을 사용하는 것이 좋습니다 .

if (( $# != 1 )); then
    echo "Illegal number of parameters"
fi

이 경우에 이것이 왜 좋은 생각일까요? 효율성, 이식성 및 기타 문제를 고려할 때 가장 간단하고 보편적으로 이해되는 구문, 즉 [ ... ]작업이 잘되고 멋진 작업이 필요 하지 않은 경우를 사용하는 것이 가장 좋지 않습니까?
최대

@Max 산술 확장 $(( ))은 환상적 이지 않으며 모든 POSIX 셸에서 구현해야합니다. 그러나 (( ))(없이 $) 구문 은 그 일부가 아닙니다. 어떤 이유로 든 제한이있는 경우 반드시 [ ]대신 사용할 수 있지만 사용해서는 안된다는 것을 명심하십시오 [[ ]]. [ ]이 기능 의 함정 과 그 이유 를 이해하기를 바랍니다 . 그러나 이것은 Bash 질문이므로 Bash 답변을 제공합니다 ( “[일반적으로 [[문자열과 파일에 사용됩니다. 숫자를 비교하려면 ArithmeticExpression을 사용하십시오]” )).
Aleks-Daniel Jakimenko-A.

39

[] :! =, =, == ...는 문자열 비교 연산자이고 -eq, -gt ...는 산술 이진 연산자 입니다.

나는 사용할 것이다 :

if [ "$#" != "1" ]; then

또는:

if [ $# -eq 1 ]; then

9
==문서화되지 않은 기능, 실제로 발생 GNU와 함께 작동하도록이 test. 또한 발생 FreeBSD에서 작동되는 test, 그러나 에서 작동하지 foo는 test . 유일한 표준 비교입니다 =(단지 참고).
Martin Tournoij

1
bash man 항목에 문서화되어 있습니다 . == 및! = 연산자를 사용하는 경우 연산자 오른쪽의 문자열은 패턴으로 간주되며 아래에 패턴 일치에 설명 된 규칙에 따라 일치됩니다. 쉘 옵션 nocasematch가 활성화되면 알파벳 문자의 경우와 상관없이 일치가 수행됩니다. 문자열이 패턴과 일치하거나 (==) 일치하지 않으면 (! =) 반환 값은 0이고, 그렇지 않으면 1입니다. 패턴의 어떤 부분이라도 문자열로 일치 시키도록 인용 될 수 있습니다.
jhvaras

2
@jhvaras : 그것은 : 그것은 Carpetsmoker 말했다 정확히 무엇을 할 수 일부 구현에서 작동 (실제로, 그것은 배쉬에서 작동), 그러나 그것은 POSIX 호환되지 않습니다 . 예를 들어 다음 과 같이 실패 합니다. POSIX는을 지정하고을 지정 하지 않습니다 . dashdash -c '[ 1 == 1 ]'===
gniourf_gniourf

34

특정 인수가 누락 된 경우에만 베일 링에 관심이 있다면 매개 변수 대체 가 좋습니다.

#!/bin/bash
# usage-message.sh

: ${1?"Usage: $0 ARGUMENT"}
#  Script exits here if command-line parameter absent,
#+ with following error message.
#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT

그것은 bashisms로로드되지 않습니까?
드와이트 스펜서

@DwightSpencer 중요한가요?
konsolebox

@Temak 구체적인 질문이있는 경우에는 할 수 있지만 링크 된 기사에서는 가능한 것보다 더 잘 설명합니다.
Pat

13

작동하는 간단한 하나의 라이너는 다음을 사용하여 수행 할 수 있습니다.

[ "$#" -ne 1 ] && ( usage && exit 1 ) || main

이것은 다음과 같이 분류됩니다.

  1. 매개 변수의 크기에 대한 bash 변수 테스트 $ #이 1과 같지 않음 (하위 명령 수)
  2. true 인 경우 usage () 함수를 호출하고 상태 1로 종료하십시오.
  3. 그렇지 않으면 main () 함수를 호출하십시오.

참고할 생각 :

  • usage ()는 간단한 에코 "$ 0 : params"일 수 있습니다.
  • main은 하나의 긴 스크립트 일 수 있습니다

1
해당 줄 다음에 다른 줄 집합이 있으면 exit 1서브 쉘의 컨텍스트에만 적용되므로이 줄과 동의어가 되기 때문에 잘못된 것 ( usage; false )입니다. 옵션 구문 분석과 관련하여 단순화 방법을 좋아하지는 않지만 { usage && exit 1; }대신 사용할 수 있습니다 . 아니면 아마도 { usage; exit 1; }.
konsolebox

1
@konsolebox (usage && exit 1)는 ksh, zsh 및 bash에서 bash 2.0으로 돌아갑니다. {...} 구문은 4.0 이상의 bash에만 있습니다. 한 가지 방법으로 잘 작동하면 잘못하지 말고 사용하십시오.하지만 모든 사람이 동일한 bash 구현을 사용하지는 않으며 bashism이 아닌 posix 표준으로 코딩해야합니다.
드와이트 스펜서

당신이 무슨 말을하는지 잘 모르겠습니다. {...}는 일반적인 구문이며 shPOSIX 표준을 따르지 않는 구형 쉘을 포함 하여 모든 쉘이 아닌 대부분의 경우에 사용할 수 있습니다 .
konsolebox

7

bash 치트 시트를 확인하십시오 . 많은 도움이 될 수 있습니다.

전달 된 인수의 길이를 확인하려면 다음을 사용하십시오. "$#"

전달 된 인수 배열을 사용하려면 "$@"

길이를 확인하고 반복하는 예는 다음과 같습니다.

myFunc() {
  if [[ "$#" -gt 0 ]]; then
    for arg in "$@"; do
      echo $arg
    done
  fi
}

myFunc "$@"

이 기사는 저에게 도움이되었지만 저와 제 상황에는 몇 가지가 빠져있었습니다. 잘하면 이것은 누군가를 돕는다.


0

안전한 편이 되려면 getopts를 사용하는 것이 좋습니다.

다음은 작은 예입니다.

    while getopts "x:c" opt; do
      case $opt in
        c)
          echo "-$opt was triggered, deploy to ci account" >&2
          DEPLOY_CI_ACCT="true"
          ;;
            x)
              echo "-$opt was triggered, Parameter: $OPTARG" >&2 
              CMD_TO_EXEC=${OPTARG}
              ;;
            \?)
              echo "Invalid option: -$OPTARG" >&2 
              Usage
              exit 1
              ;;
            :)
              echo "Option -$OPTARG requires an argument." >&2 
              Usage
              exit 1
              ;;
          esac
        done

예를 들어 http://wiki.bash-hackers.org/howto/getopts_tutorial에 대한 자세한 내용을 참조하십시오 .


0

다음은 하나의 매개 변수 만 제공되는지 확인하는 간단한 라이너 하나입니다. 그렇지 않으면 스크립트를 종료하십시오.

[ "$#" -ne 1 ] && echo "USAGE $0 <PARAMETER>" && exit

-1

테스트 조건 사이에 공백을 추가해야합니다.

if [ $# -ne 1 ]; 
    then echo "illegal number of parameters"
fi

이게 도움이 되길 바란다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.