getopts를 사용하여 Linux 셸 스크립트 옵션을 구문 분석하는 방법

게시 됨: 2022-06-25
터미널 텍스트를 보여주는 노트북 화면.
Fatmawati achmad zaenuri/Shutterstock.com

Linux 셸 스크립트가 명령줄 옵션과 인수를 보다 우아하게 처리하기를 원하십니까? Bash getopts 내장을 사용하면 기교로 명령줄 옵션을 구문 분석할 수 있으며, 그것도 쉽습니다. 우리는 당신에게 방법을 보여줍니다.

getopt 내장 소개

Bash 스크립트에 을 전달하는 것은 꽤 간단한 문제입니다. 명령줄이나 다른 스크립트에서 스크립트를 호출하고 스크립트 이름 뒤에 값 목록을 제공합니다. 이 값은 첫 번째 변수에 대해 $1 , 두 번째 변수에 대해 $2 등으로 시작하여 스크립트 내에서 변수로 액세스할 수 있습니다.

그러나 스크립트에 옵션 을 전달하려는 경우 상황이 빠르게 더 복잡해집니다. 옵션이라고 하면 ls 와 같은 프로그램이 처리할 수 있는 옵션, 플래그 또는 스위치를 의미합니다. 대시 " - "가 앞에 오고 일반적으로 프로그램이 기능의 일부를 켜거나 끄도록 지시하는 역할을 합니다.

ls 명령을 사용하여 Linux에서 파일 및 디렉토리를 나열하는 방법
관련 Linux에서 ls 명령을 사용하여 파일 및 디렉토리를 나열하는 방법

ls 명령에는 주로 출력 형식 지정과 관련된 50개 이상의 옵션이 있습니다. -X (확장자별 정렬) 옵션은 출력을 파일 확장자별로 알파벳순으로 정렬합니다. -U (정렬되지 않음) 옵션은 디렉토리 순서로 나열됩니다.

옵션은 선택 사항일 뿐입니다. 사용자가 어떤 옵션을 사용할지(있는 경우) 알지 못하며 명령줄에 어떤 순서로 나열할지 모릅니다. 이것은 옵션을 구문 분석하는 데 필요한 코드의 복잡성을 증가시킵니다.

일부 옵션이 옵션 인수 라고 하는 인수를 사용하는 경우 상황은 더욱 복잡해집니다. 예를 들어 ls -w (width) 옵션은 출력의 최대 표시 너비를 나타내는 숫자가 뒤에 올 것으로 예상합니다. 물론 옵션이 아닌 단순히 데이터 값인 다른 매개변수를 스크립트에 전달할 수도 있습니다.

고맙게도 getopts 는 이러한 복잡성을 처리합니다. 그리고 내장형이기 때문에 Bash 셸이 있는 모든 시스템에서 사용할 수 있으므로 설치할 필요가 없습니다.

참고: getopts getopt 아님

getopt 라는 오래된 유틸리티가 있습니다. 이것은 내장이 아닌 작은 유틸리티 프로그램 입니다. 다른 동작을 가진 getopt 의 여러 버전이 있지만 getops 내장은 POSIX 지침을 따릅니다.

 유형 getopts
 유형 getopt 

type 명령을 사용하여 getop과 getops의 차이점 보기

getopt 는 내장 기능이 아니기 때문에 공백을 현명하게 처리하는 것과 같이 getopts 가 제공하는 일부 자동 이점을 공유하지 않습니다. getopts 를 사용하면 Bash 셸이 스크립트를 실행하고 Bash 셸이 옵션 구문 분석을 수행합니다. 구문 분석을 처리하기 위해 외부 프로그램을 호출할 필요가 없습니다.

절충점은 getopts 가 이중 대시, 긴 형식 옵션 이름을 처리하지 않는다는 것입니다. 따라서 -w 와 같은 형식의 옵션을 사용할 수 있지만 " ---wide-format "은 사용할 수 없습니다. 반면에 -a , -b-c 옵션을 허용하는 스크립트가 있는 경우 getopts 를 사용하면 -abc , -bca 또는 -abc -bac 같은 옵션을 결합할 수 있습니다.

이 기사에서 getopts 에 대해 논의하고 시연하므로 명령 이름에 마지막 "s"를 추가해야 합니다.

관련: Windows 명령줄에서 파일 경로의 공백을 탈출하는 방법

요약: 매개변수 값 처리

이 스크립트는 -a 또는 -b 와 같은 대시 옵션을 사용하지 않습니다. 명령줄에서 "일반" 매개변수를 허용하고 스크립트 내에서 값으로 액세스합니다.

 #!/bin/bash

# 변수를 하나씩 가져옵니다.
echo "변수 1: $1" 
echo "변수 2: $2" 
echo "변수 3: $3"

# 변수를 순환
" $@"의 var에 대해 수행
echo "$ var" 
완료

매개변수는 스크립트 내에서 $1 , $2 또는 $3 변수로 액세스됩니다.

이 텍스트를 편집기에 복사하고 "variables.sh"라는 파일로 저장합니다. chmod 명령으로 실행 가능하게 만들어야 합니다. 논의하는 모든 스크립트에 대해 이 단계를 수행해야 합니다. 매번 적절한 스크립트 파일의 이름을 바꾸십시오.

 chmod +x 변수.sh 

chmod 명령을 사용하여 스크립트를 실행 가능하게 만들기

매개변수 없이 스크립트를 실행하면 이 출력을 얻습니다.

 ./변수.sh 

매개변수 없이 스크립트 실행

스크립트에 보고할 값이 없으므로 매개변수를 전달하지 않았습니다. 이번에는 몇 가지 매개변수를 제공하겠습니다.

 ./variables.sh 괴짜하는 법 

세 단어를 매개변수로 사용하여 스크립트 실행

예상대로 $1 , $2$3 변수가 매개변수 값으로 설정되었으며 인쇄된 것을 볼 수 있습니다.

이 유형의 일대일 매개변수 처리는 얼마나 많은 매개변수가 있는지 미리 알아야 함을 의미합니다. 스크립트 맨 아래에 있는 루프는 매개변수가 몇 개인지 상관하지 않고 항상 모든 매개변수를 반복합니다.

네 번째 매개변수를 제공하면 변수에 할당되지 않지만 루프는 여전히 이를 처리합니다.

 ./variables.sh 괴짜 웹 사이트 방법 

3개만 처리할 수 있는 스크립트에 4개의 매개변수 전달

두 단어 주위에 따옴표를 넣으면 하나의 매개변수로 처리됩니다.

 ./variables.sh "괴짜" 방법 

두 개의 명령줄 매개변수를 인용하여 하나의 매개변수로 처리

옵션, 인수가 있는 옵션 및 "일반" 데이터 유형 매개변수의 모든 조합을 처리하는 스크립트가 필요한 경우 일반 매개변수에서 옵션을 분리해야 합니다. 인수가 있든 없든 모든 옵션을 일반 매개변수 앞에 배치하여 이를 달성할 수 있습니다.

그러나 걷기 전에 뛰지 맙시다. 명령줄 옵션을 처리하는 가장 간단한 경우를 살펴보겠습니다.

취급 옵션

while 루프에서 getopts 를 사용합니다. 루프의 각 반복은 스크립트에 전달된 하나의 옵션에서 작동합니다. 각 경우에 변수 OPTIONgetopts 로 식별되는 옵션으로 설정됩니다.

루프가 반복될 때마다 getopts 는 다음 옵션으로 이동합니다. 더 이상 옵션이 없으면 getoptsfalse 를 반환하고 while 루프가 종료됩니다.

Bash 스크립트에서 Case 문을 사용하는 방법
관련 Bash 스크립트에서 Case 문을 사용하는 방법

OPTION 변수는 각 case 문 절의 패턴과 일치합니다. case 문을 사용하기 때문에 명령줄에서 옵션이 제공되는 순서는 중요하지 않습니다. 각 옵션이 case 문에 삭제되고 적절한 절이 트리거됩니다.

case 문의 개별 절을 사용하면 스크립트 내에서 옵션별 작업을 쉽게 수행할 수 있습니다. 일반적으로 실제 스크립트에서 각 절에 변수를 설정하면 스크립트에서 플래그 역할을 하여 일부 기능을 허용하거나 거부합니다.

이 텍스트를 편집기에 복사하고 "options.sh"라는 스크립트로 저장하고 실행 가능하게 만드십시오.

 #!/bin/bash

getopts 'abc' OPTION 동안; 하다
  대소문자 "$OPTION" 
    ㅏ) 
      echo "사용된 옵션" ;;

    비)
      echo "옵션 b 사용됨"
      ;;

    씨)
      echo "옵션 c 사용"
      ;;

    ?) 
      echo "사용법: $(기본 이름 $0) [-a] [-b] [-c]"
      1번 출구
      ;;
  이삭
완료

이것은 while 루프를 정의하는 라인입니다.

 getopts 'abc' OPTION 동안; 하다

getopts 명령 뒤에는 옵션 문자열 이 옵니다. 이것은 우리가 옵션으로 사용할 문자를 나열합니다. 이 목록의 문자만 옵션으로 사용할 수 있습니다. 따라서 이 경우 -d 는 유효하지 않습니다. 이것은 getopts 가 물음표 ? ?) " 미확인 옵션의 경우. 이 경우 올바른 사용법이 터미널 창에 인쇄됩니다.

 echo "사용법: $(기본 이름 $0) [-a] [-b] [-c]"

규칙에 따라 이러한 유형의 올바른 사용법 메시지에서 대괄호 " [] "로 옵션을 묶는 것은 옵션이 선택 사항임을 의미합니다. basename 명령은 파일 이름에서 모든 디렉토리 경로를 제거합니다. 스크립트 파일 이름은 Bash 스크립트에서 $0 에 보관됩니다.

이 스크립트를 다른 명령줄 조합과 함께 사용하겠습니다.

 ./options.sh -a
 ./options.sh -a -b -c
 ./options.sh -ab -c
 ./options.sh -택시 

스위치 유형 명령줄 옵션을 허용할 수 있는 스크립트 테스트

보시다시피 옵션의 모든 테스트 조합은 구문 분석되고 올바르게 처리됩니다. 존재하지 않는 옵션을 시도하면 어떻게 될까요?

 ./options.sh -d 

쉘 및 스크립트에서 보고되는 인식할 수 없는 옵션

사용 절이 트리거되며 이는 양호하지만 셸에서 오류 메시지도 받습니다. 그것은 당신의 사용 사례에 중요할 수도 있고 중요하지 않을 수도 있습니다. 오류 메시지를 구문 분석해야 하는 다른 스크립트에서 스크립트를 호출하는 경우 셸에서도 오류 메시지를 생성하는 경우 더 어렵게 만듭니다.

쉘 오류 메시지를 끄는 것은 매우 쉽습니다. 우리가 해야 할 일은 옵션 문자열의 첫 번째 문자로 콜론 " : "을 넣는 것뿐입니다.

"options.sh" 파일을 편집하고 옵션 문자열의 첫 번째 문자로 콜론을 추가하거나 이 스크립트를 "options2.sh"로 저장하고 실행 가능하게 만드십시오.

 #!/bin/bash

getopts ':abc' OPTION; 하다
  대소문자 "$OPTION" 
    ㅏ) 
      echo "사용된 옵션" 
      ;;

    비)
      echo "옵션 b 사용됨"
      ;;

    씨)
      echo "옵션 c 사용"
      ;;

    ?) 
      echo "사용법: $(기본 이름 $0) [-a] [-b] [-c]"
      1번 출구
      ;;
  이삭
완료

이것을 실행하고 오류를 생성하면 쉘 메시지 없이 자체 오류 메시지가 수신됩니다.

 ./options2.sh.sh -d 

스크립트만으로 보고되는 인식할 수 없는 옵션

옵션 인수와 함께 getopts 사용

옵션 뒤에 인수가 온다는 것을 getopts 에게 알리려면 옵션 문자열에서 옵션 문자 바로 뒤에 콜론 " : "을 넣으십시오.

옵션 문자열에서 "b"와 "c" 뒤에 콜론이 있으면 getopt 는 이러한 옵션에 대한 인수를 예상합니다. 이 스크립트를 편집기에 복사하고 "arguments.sh"로 저장하고 실행 가능하게 만드십시오.

옵션 문자열의 첫 번째 콜론은 셸 오류 메시지를 억제하는 데 사용되며 인수 처리와 관련이 없습니다.

getopt 가 인수가 있는 옵션을 처리할 때 인수는 OPTARG 변수에 배치됩니다. 스크립트의 다른 곳에서 이 값을 사용하려면 다른 변수에 복사해야 합니다.

 #!/bin/bash

getopts ':ab:c:' OPTION; 하다

  대소문자 "$OPTION"
    ㅏ)
      echo "사용된 옵션"
      ;;

    비)
      argB="$OPTARG"
      echo "옵션 b 사용: $argB"
      ;;

    씨)
      argC="$OPTARG"
      echo "다음과 함께 사용되는 옵션: $argC"
      ;;

    ?)
      echo "사용법: $(basename $0) [-a] [-b 인수] [-c 인수]"
      1번 출구
      ;;
  이삭

완료

그것을 실행하고 그것이 어떻게 작동하는지 봅시다.

 ./arguments.sh -a -b "괴짜 방법" -c reviewgeek
 ./arguments.sh -c reviewgeek -a 

옵션 인수를 처리할 수 있는 스크립트 테스트

이제 명령줄에 지정된 순서에 관계없이 인수가 있거나 없는 옵션을 처리할 수 있습니다.

하지만 일반 매개변수는 어떻습니까? 우리는 이전에 옵션 뒤에 명령줄에 넣어야 한다는 것을 알고 있다고 말했습니다. 하면 어떻게 되는지 봅시다.

혼합 옵션 및 매개변수

한 줄 더 포함하도록 이전 스크립트를 변경합니다. while 루프가 종료되고 모든 옵션이 처리되면 일반 매개변수에 액세스하려고 합니다. $1 의 값을 출력할 것입니다.

이 스크립트를 "arguments2.sh"로 저장하고 실행 가능하게 만드십시오.

 #!/bin/bash

getopts ':ab:c:' OPTION; 하다

  대소문자 "$OPTION"
    ㅏ)
      echo "사용된 옵션"
      ;;

    비)
      argB="$OPTARG"
      echo "옵션 b 사용: $argB"
      ;;

    씨)
      argC="$OPTARG"
      echo "다음과 함께 사용되는 옵션: $argC"
      ;;

    ?)
      echo "사용법: $(basename $0) [-a] [-b 인수] [-c 인수]"
      1번 출구
      ;;
  이삭

완료

echo "변수 1: $1"

이제 몇 가지 옵션과 매개변수 조합을 시도해 보겠습니다.

 ./arguments2.sh 데이브
 ./arguments2.sh -a 데이브
 ./arguments2.sh -a -c How-to-geek 데이브 

옵션 인수를 허용하는 스크립트의 표준 매개변수에 액세스하지 못함

이제 우리는 문제를 볼 수 있습니다. 옵션이 사용되는 즉시 $1 이후의 변수는 옵션 플래그와 해당 인수로 채워집니다. 마지막 예에서 $4 는 매개변수 값 "dave"를 보유하지만 얼마나 많은 옵션과 인수가 사용될지 모르는 경우 스크립트에서 어떻게 액세스합니까?

대답은 OPTINDshift 명령을 사용하는 것입니다.

shift 명령은 유형에 관계없이 매개변수 목록에서 첫 번째 매개변수를 버립니다. 다른 매개변수는 "셔플다운"하므로 매개변수 2는 매개변수 1이 되고 매개변수 3은 매개변수 2가 되는 식입니다. 따라서 $2$1 이 되고 $3$2 가 되는 식입니다.

shift 에 숫자를 제공하면 목록에서 그만큼 많은 매개변수가 제거됩니다.

OPTIND 는 발견되고 처리되는 옵션과 인수를 계산합니다. 모든 옵션과 인수가 처리되면 OPTIND 는 옵션 수보다 하나 더 높습니다. 따라서 shift를 사용하여 매개변수 목록에서 (OPTIND-1) 매개변수를 트리밍하면 $1 이후에 일반 매개변수가 남게 됩니다.

이것이 바로 이 스크립트가 하는 일입니다. 이 스크립트를 "arguments3.sh"로 저장하고 실행 가능하게 만드십시오.

 #!/bin/bash

getopts ':ab:c:' OPTION; 하다
  대소문자 "$OPTION"
    ㅏ)
      echo "사용된 옵션"
      ;;

    비)
      argB="$OPTARG"
      echo "옵션 b 사용: $argB"
      ;;

    씨)
      argC="$OPTARG"
      echo "다음과 함께 사용되는 옵션: $argC"
      ;;

    ?)
      echo "사용법: $(basename $0) [-a] [-b 인수] [-c 인수]"
      1번 출구
      ;;
  이삭
완료

echo "이전 - 변수 1은 $1입니다."
시프트 "$(($OPTIND -1))"
echo "후 - 변수 1은: $1"
echo "나머지 인수(피연산자)"

"$@"의 x에 대해
하다
  에코 $x
완료

옵션, 인수 및 매개변수를 혼합하여 이것을 실행할 것입니다.

 ./arguments3.sh -a -c 괴짜 "dave dee" dozy beaky mick tich 사용법 

옵션 인수를 허용하는 스크립트에서 표준 매개변수에 올바르게 액세스

shift 를 호출하기 전에는 $1 이 "-a"를 유지했지만 shift 명령 이후에는 $1 이 첫 번째 비옵션, 비인수 매개변수를 보유하고 있음을 알 수 있습니다. 옵션 구문 분석 없이 스크립트에서 하는 것처럼 쉽게 모든 매개변수를 반복할 수 있습니다.

항상 옵션이 있는 것이 좋습니다.

스크립트에서 옵션과 해당 인수를 처리하는 것은 복잡할 필요가 없습니다. getopts 를 사용하면 POSIX 호환 기본 스크립트와 똑같이 명령줄 옵션, 인수 및 매개변수를 처리하는 스크립트를 만들 수 있습니다.