while 루프 내에서 함수를 호출할 때 getopts는 매개변수를 가져오지 않습니다.

while 루프 내에서 함수를 호출할 때 getopts는 매개변수를 가져오지 않습니다.

while 루프에서 함수를 호출하고 일부 매개변수를 전달하려고 합니다. 그러나 getopts첫 번째 호출의 매개변수만 얻을 수 있습니다.

다음은 최소한의 예입니다.

function add_all_external_services() {
  env | sed -n "s/^EXTERNAL_SERVICE_OPTIONS_\(.*\)$/\1/p" > options

  while read -r line
  do
    key="${line%%=*}"
    opt="${line#*=}"

    if [[ -n "$key" && -n "$opt" ]]; then
      echo "Adding external service \"$key\" with options: \"$opt\""
      add_external_service $opt
    else
      echo "Missing one or more variables:
  - Key: \"$key\"
  - Options: \"$opt\"
"
    fi
  done < options

  rm options
}

function add_external_service() {
  local local_service_name=""
  local external_service_name=""
  local external_service_namespace=""
  local service_url=""

  echo "    Options: $@"
  while getopts l:s:n:-: OPT; do
    if [[ "$OPT" = "-" ]]; then   # long option: reformulate OPT and OPTARG
      OPT="${OPTARG%%=*}"         # extract long option name
      OPTARG="${OPTARG#$OPT}"     # extract long option argument (may be empty)
      OPTARG="${OPTARG#=}"        # if long option argument, remove assigning `=`
    fi
    case "$OPT" in
      l | local-service-name)           needs_arg; local_service_name="$OPTARG" ;;
      s | external-service-name)        needs_arg; external_service_name="$OPTARG" ;;
      n | external-service-namespace)   needs_arg; external_service_namespace="$OPTARG" ;;
      external-name)                    needs_arg; service_url="$OPTARG" ;;
      ??* )                             die "Illegal option --$OPT" ;;  # bad long option
      \? )                              exit 2 ;;  # bad short option (error reported via getopts)
    esac
  done

  echo "      - local $local_service_name"
  echo "      - name $external_service_name"
  echo "      - namespace $external_service_namespace"
  echo "      - url $service_url"
}

그런 다음 전화할 때:

export EXTERNAL_SERVICE_OPTIONS_A="-l local_a -s rasa -n botinstance-12424526-review-feature-ce-swdjtf"
export EXTERNAL_SERVICE_OPTIONS_B="-l local_b -s review-feature-ce-swdjtf -n botinstance-12424526-review-feature-ce-swdjtf"

ventury-deploy add_all_external_services

알겠어요:

Adding external service "B" with options: "-l local_b -s name_b -n namespace_b"
    Options: -l local_b -s name_b -n namespace_b
      - local local_b
      - name name_b
      - namespace namespace_b
      - url 
Adding external service "A" with options: "-l local_a -s name_a -n namespace_a"
    Options: -l local_a -s name_a -n namespace_a
      - local 
      - name 
      - namespace 
      - url 

내가 얻은 getopts부분여기루프 외부에서 함수를 호출할 때마다 정상적으로 작동합니다.

읽고 나서이 문제&루프 내에서 함수를 호출한 후 추가를 시도했는데 작동했습니다. 모든 매개변수가 에 의해 전달되었습니다 getopts. 백그라운드에서 명령을 실행하면 작동하는 이유를 이해할 수 없습니다.

echo $@이전에 가면 모든 getopts매개변수가 올바르게 전달되는 것을 볼 수 있으며, 두 번째 함수를 각 env 변수에 대해 한 번씩 수동으로 호출해도 제대로 작동합니다.

그렇다면 이러한 명령을 백그라운드에서 실행하는 것의 차이점은 무엇입니까? 내 말은, 차이점이 무엇입니까 getopts? 또한 echo $@매개변수는 볼 수 있는데 왜 볼 수 getopts없나요?

답변1

재설정하지 않았기 때문입니다 OPTIND. ~에 따르면수동:

각 호출에서 getopts는 다음 옵션을 쉘 변수 이름에 배치하고 이름이 존재하지 않으면 초기화하며 처리할 다음 인수의 인덱스를 변수 OPTIND에 배치합니다. OPTIND는 쉘이나 쉘 스크립트가 호출될 때마다 1로 초기화됩니다.

따라서 OPTIND는 처리할 다음 인수를 추적하는 데 사용되며 1스크립트가 시작될 때 자동으로 설정되지만 함수가 끝날 때 재설정되지는 않습니다.

스크립트를 수정하려면 OPTIND=1함수 시작 부분에 다음을 추가하세요.

function add_external_service() {
  OPTIND=1
  local local_service_name=""
  local external_service_name=""
  local external_service_namespace=""
  local service_url=""

  echo "    Options: $@"
  while getopts l:s:n:-: OPT; do
    if [[ "$OPT" = "-" ]]; then   # long option: reformulate OPT and OPTARG
      OPT="${OPTARG%%=*}"         # extract long option name
      OPTARG="${OPTARG#$OPT}"     # extract long option argument (may be empty)
      OPTARG="${OPTARG#=}"        # if long option argument, remove assigning `=`
    fi
    case "$OPT" in
      l | local-service-name)           needs_arg; local_service_name="$OPTARG" ;;
      s | external-service-name)        needs_arg; external_service_name="$OPTARG" ;;
      n | external-service-namespace)   needs_arg; external_service_namespace="$OPTARG" ;;
      external-name)                    needs_arg; service_url="$OPTARG" ;;
      ??* )                             die "Illegal option --$OPT" ;;  # bad long option
      \? )                              exit 2 ;;  # bad short option (error reported via getopts)
    esac
  done

  echo "      - local $local_service_name"
  echo "      - name $external_service_name"
  echo "      - namespace $external_service_namespace"
  echo "      - url $service_url"
}

관련 정보