"--" 뒤에 인식할 수 없는 옵션을 남겨두고 Bash 스크립트에서 옵션을 구문 분석하는 방법은 무엇입니까?

"--" 뒤에 인식할 수 없는 옵션을 남겨두고 Bash 스크립트에서 옵션을 구문 분석하는 방법은 무엇입니까?

Bash 스크립트에서 옵션 구문 분석을 수행하는 방법을 찾고 있습니다(예: 짧은 매개변수와 긴 매개변수를 모두 허용).선택 항목 가져오기실제로) 인식할 수 없는 첫 번째 인수에서 구문 분석을 중지하고--인식할 수 없는 첫 번째 매개변수 앞에, 나머지 매개변수를 출력 문자열에 복사합니다.

예를 들어, 내가 원하는 동작은 다음과 같습니다.

% OPTIONS=("-u" "name1" "--username=name2" "-x" "a" -u "b" "c")
% getopt -o u: -l username: -n programname -- "${OPTIONS[@]}"
-u 'name1' --username 'name2' -- -x 'a' -u 'b' 'c'
%

getopt 유틸리티는 이런 방식으로 작동하지 않고 대신 다음을 내보냅니다.

programname: invalid option -- 'x'
-u 'name1' --username 'name2' -u 'b' -- 'a' 'c'

위의 두 번째 항목에 표시된 것처럼 인식할 수 없는 옵션 뒤에 오는 인수가 인식된 것처럼 재정렬되는 것을 원하지 않습니다.-유옵션. 누군가가 위의 첫 번째 코드 블록에서 설명한 결과를 제공하는 솔루션을 찾을 수 있기를 바랍니다. 어떤 아이디어가 있나요?

환경:배시 4.2.46(1), CentOS 7.2 @3.10.0-327.36.1.el7.x86_64.

필요하다:CentOS 7.2 Minimal, 다른 소프트웨어를 설치할 필요가 없으며 모든 코드는 Bash 스크립트로 작성됩니다. 옵션 파서에 전달된 옵션에는 다음이 포함될 필요가 없습니다.--(즉, 구문 분석 종료는 자동으로 이루어져야 합니다)

답변1

이 문제를 해결하려면 다른 것이 필요합니다선택 항목 가져오기왜냐하면선택 항목 가져오기재배열하면 옵션 사양과 일치하는 옵션을 찾고, 인식할 수 없는 옵션에서는 종료됩니다. 배쉬 내장선택 항목 가져오기구조하러 오세요. 그러나 장기적인 옵션을 처리할 수 있어야 합니다. 게시물에Arvid Requate와 TomRoche, 만들 수 있는 "트릭"이 있습니다.선택 항목 가져오기긴 옵션을 처리하려면 다음을 사용하세요.-옵션 사양으로 사용하고 옵션 사양에 앞에 콜론을 사용하여 오류 보고를 제거합니다. 그러나 해당 솔루션에서는 짧은 옵션과 긴 옵션을 처리하기 위해 코드 중복이 필요합니다.

다음은 제가 테스트한 솔루션이며 모든 요구 사항을 충족하고 짧은 옵션과 긴 옵션을 중복하지 않습니다. 명확성과 완전성을 위해 나는 변경했습니다사용자 이름도착하다놓다그리고 추가됨스위치가치가 없는 옵션을 보여줍니다.

파서

#!/bin/bash

Options=("$@")
while getopts ":s:-:" OptChar "${Options[@]}"; do
   case "$OptChar" in
    -)   case "$OPTARG" in
         set|set=*)
            if [[ $OPTARG =~ ^set= ]] ; then
               Value="${Options[$OPTIND-2]#*=}"
            else
               Value="${Options[$OPTIND-1]}"
               ((OPTIND++))
            fi
            echo "Parsed: --$OPTARG, value: '$Value'"
            ;;

         toggle)
            echo "Parsed: --$OPTARG";;
         *) ((OPTIND--)); break;;
         esac
         ;;

   # Redirect short arguments to long arguments
   s)    ((OPTIND-=2)); Options[OPTIND-1]="--set";;
   t)    ((OPTIND--)); Options[OPTIND-1]="--toggle";;

   *)    ((OPTIND--)); break;;
   esac
done
Options=( "${Options[@]:$OPTIND-1}" )

echo "REMAINING Options: ${Options[@]}"

이것은 내 테스트 코드입니다.

% ./parse.sh --set=a  -s b --set= --set c --unknown -s d --set e
Parsed: --set=a, value: 'a'
Parsed: --set, value: 'b'
Parsed: --set=, value: ''
Parsed: --set, value: 'c'
REMAINING Options: --unknown -s d --set e
%
% ./parse.sh -s a -x -s b
Parsed: --set, value: 'a'
REMAINING Options: -x -s b
%

답변2

"-ax"와 같은 짧은 옵션을 결합하여 사용하지 않으면 이 방법이 작동할 수 있습니다.

OPTIONS=("-u" "name1" "--username=name2" "-x" "a" -u "b" "c")

for i in `seq ${#OPTIONS[@]} -1 0`; do
  OFIRST=("${OPTIONS[@]:0:$i}")
  getopt -o u: -l username: -n programname -- "${OFIRST[@]}" &>/dev/null && break
done

NEWOPT=("${OPTIONS[@]:0:$i}" "--"  "${OPTIONS[@]:$i}")

getopt -o u: -l username: -n programname -- "${NEWOPT[@]}"

이 솔루션에 문제가 있다고 확신합니다. 아마도 이 기능을 util-linux의 getopt.c 소스 코드에 추가하는 것이 더 나을 것입니다.

관련 정보