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パラメータが正しく渡されることがわかりますが、2つ目の関数を各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"
}

おすすめ記事