getopts를 사용하여 삽입된 값으로 작업하는 방법

getopts를 사용하여 삽입된 값으로 작업하는 방법

나는 이 bash 코드를 getopts와 결합했고, getopts를 올바르게 이해했다면 OPTIND에는 다음 명령줄 옵션의 인덱스가 포함되어 있으며 쉘 스크립트에 제공된 모든 명령줄 옵션은 변수 $1, $2, $3 등에 표시됩니다. 그렇다면 제 말을 정정해 주십시오. 제가 틀렸지만 기본적으로 함수의 지역 변수와 동일한 개념입니다.

그래서 이것에 따르면 옵션이 나에게 어떤 결과도 제공 [-a somevalue ]하지 않는 이유는 무엇입니까? [-b somevalue ]내가 뭘 잘못했나요?

OPT_A=A
OPT_B=B

while getopts :a:b FLAG; do
 case $FLAG in
    a) 
      OPT_A=$OPTARG
      ;;
    b) 
     OPT_B=$OPTARG
      ;;
  esac
done

shift $((OPTIND-1))

    while [ $# -ne 0 ]; do

if [[ -z $OPT_A ]]; then
    if [ `echo $1 | grep -o '\.' | wc -l` -ne 3 ]; then
        echo "Parameter '$1' does not look like an IP Address (does not contain 3 dots).";
            exit 1;
        elif [ `echo $1 | tr '.' ' ' | wc -w` -ne 4 ]; then
            echo "Parameter '$1' does not look like an IP Address (does not contain 4 octets).";
        exit 1;
            else
        for OCTET in `echo $1 | tr '.' ' '`; do
                if ! [[ $OCTET =~ ^[0-9]+$ ]]; then
                        echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' is not numeric).";
                        exit 1;
                elif [[ $OCTET -lt 0 || $OCTET -gt 255 ]]; then
                        echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' in not in range 0-255).";
                        exit 1;
                fi
        done
    fi
fi


if [[ -z $OPT_B ]]; then
        if [[ "$2" =~ ^[0-9]+$ ]] && [ "$2" -ge 1 -a "$2" -le 10000 ]; then 
            echo "chosen variable: $2";
            exit 1;
            else echo "variable $2 is not in range '1 - 10000'";
            exit 1;
        fi
    fi

    done
    exit 0

답변1

이는 모든 논리가 그 중 하나가 $OPT_[AB]비어 있어야 하기 때문입니다. 하지만 매개 변수를 전달하지 않더라도 -[ab] $OPTARG계속 사용할 수 있습니다 OPT_[AB]=[AB]. 따라서 논리 체인은 루트를 통과하지 못합니다.

if [[ -z $OPT_A ]]; then...

...성명.

음 .. 아니야모두당신의 논리는 이것에 달려 있습니다. 당신은 또한 다음을 하고 있습니다:

shift $((OPTIND-1))

    while [ $# -ne 0 ]...

따라서 통과하면 3 으로 설정 script -a arg됩니다 . 그래서 당신은 것입니다getopts$OPT_Aarg$OPTINDshift 2 (모든 게시물)그러면 테스트가 즉시 실패합니다 while. 따라서 을 case설정하면 $OPT_A다음에 일어날 일은 입니다 exit 0. 그래서 $OPT_A사용 가능한지 확인하지 않은 것 같습니다 .

그럼에도 불구하고 대부분의 논리는 테스트 실패를 위해 설계되었으므로 중요하지 않습니다. 그러나 스크립트는오직 exit에스. var를 만들었지 $OPT_A만 아무 작업도 수행하지 않을 수 있습니다. 스크립트 후에는 이 값을 사용할 수 없습니다 exit. 미리 설정된 IPC가 없지만 여기에는 그런 것이 없습니다. 스크립트는 서브쉘에서 호출되며, 상위 쉘로 돌아가면 설정한 값은 손실됩니다.

더 중요한 것은 :a:boptstring $OPTARG-b. optstring의 선행 콜론은 자동 작동을 나타냅니다. stderr옵션이나 해당 인수에 문제가 있으면 기록되지 않습니다. 하지만 콜론뒤따라옵션 문자는 옵션에 인수가 있어야 함을 나타냅니다. 좋다:

while getopts :a:b: FLAG

...인수가 필요한 두 가지 옵션을 나타냅니다. 그러나 이는 까다로울 수 있습니다. 인수를 허용해야 한다고 표시한 후 getopts인수가 없는 것으로 확인되면 오류로 표시되기 때문입니다.

sh -c 'getopts :a:b: opt -a; echo "$opt $OPTARG"'

...인쇄...

: a

이 경우 옵션은 결국 가 됩니다 $OPTARG. 우리가 그것에 대해 덜 침묵한다면 그것은 더 명확해질 것입니다::$opt:

sh -c 'getopts a:b: opt -a; echo "$opt $OPTARG"'
No arg for -a option

:따라서 콜론을 확인해야 하며 ?이는 일반적으로 간단한 내용을 인쇄하기 위해 경로를 재설정하는 또 다른 유형의 오류입니다 --help.

$OPT_[AB]개인적으로 저는 처음부터 그것들이 모두 비어 있는지 확인하고 몇 가지 논리를 수행하여 올바르게 설정한 다음 테스트 루프를 완료한 후 마지막 테스트를 비어 있도록 설정합니다. 그것들이 전혀 가치가 없다면 그것은 내가 다루지 않는 어떤 이유에서임에 틀림없으며 어쨌든 그것은 버그입니다. 이것이 테스트 루프를 수행하는 방법의 시작입니다...

param_err(){
    set '' "$@"
    : "${1:?Parameter '$OPTARG' does not look like an IP Address $2}"
}

test_oct(){ 
    oIFS=$IFS; unset "${IFS+o}oIFS"; IFS=.
    for oct in $1; do  [ $oct -lt 256 ] || 
        param_err "('$oct' too large)"
    done; unset IFS oct
    : "${oIFS+${IFS=$oIFS}}"
}

a_param()
    case ${1##*.*.*.*.*} in (a) OPT_A=A;;  #some default - no arg provided                                            
          (.*|*..*|*.) param_err '(empty octet)';;
          (*[!.0-9]*)  param_err '(octet is not positive integer)';;
          (*.*.*.*)    test_oct  "$1"; OPT_A=$1;;
          (*?*)        param_err '(too few octets)';;
          (*)          param_err ${1:+"(too many octets)"} '(null param)';;
    esac

unset OPT_A OPT_B
while getopts :a:b:c:d: opt
do    case ${opt#:}$OPTARG in
      a*)   a_param "$OPTARG";;
      b*)   b_param "$OPTARG";; #tests as needed similar to a_param()
      ?*)   help;;              #param_err should call this too, but it just exits
      esac
done                

답변2

상단에 셔뱅라인이 없으므로 사용중인 쉘( sh, dash)이 이를 지원하지 않을 수 있습니다 [[. 다음 명령을 사용하여 스크립트를 시작해야 합니다.

#!/bin/bash

또는 다른 위치 bash(만약 이것이 시스템의 bash 경로가 아닌 경우 type bash).

답변3

이것을 변경해보세요: while getopts :a:b FLAG do;

이를 위해: while getopts :a:b: FLAG;

관련 정보