Bash:サブシェルでグローバル変数を作成する

Bash:サブシェルでグローバル変数を作成する

getopts複数回使用できるように、いくつかのロジックを関数に移動して、ユーザーに指定されたパラメータの順序でより柔軟性を提供したいと思います。

print-usage() {
echo "myssh [options] <host> [options] [-- ssh-options...]" >&2
exit 1
}

extra_args=()

parse-args() {
  while getopts ":hvV:" opt; do
    case ${opt} in
      (h)  print-usage ;;
      (v)  extra_args+=('-L 5900:localhost:5900')    ;;
      (V)  extra_args+=("-L $OPTARG:localhost:5900") ;;
      (\?) echo "Invalid option: -$OPTARG" >&2       ;;
      (:)  echo "Invalid option: -$OPTARG requires an argument" >&2 ;;
    esac
  done
  echo $((OPTIND -1))
}

shift $(parse-args $@)

host=$1
shift

shift $(parse-args $@)

ssh $host $extra_args $@

私の問題は、これがparse-args() { ... extra_args+=(...) }グローバル変数に影響を与えないことですextra_args。私はサブシェルが親範囲変数に書き込むことができず、通常はstdoutを使用する必要があることを知っていますが、stdoutを移動した整数として使用しました。

この問題は通常どのように解決されますか?

ベストアンサー1

(タグ付き)使用しているので、bash配列変数を使用できます。できないことは、サブシェルのshift $(parse_args "$@")thisのような呼び出しを介してグローバル変数に影響を与えることです。parse_args以下は、関数の外部に値の配列を渡す代替ソリューションです。

#!/bin/bash
#
extra_args1=()
extra_args2=()

usage() {
    echo "myssh [options] <host> [options] [-- ssh-options...]" >&2
    exit 1
}
    
parse_args() {
    local OPT OPTIND=1 OPTARG args=()
    while getopts ":hvV:" OPT
    do
        case "$OPT" in
            (h)   usage ;;
            (v)   args+=('-L' '5900:localhost:5900') ;;
            (V)   args+=('-L' "$OPTARG:localhost:5900") ;;
            (\?)  echo "Invalid option: -$OPTARG" >&2 ;;
            (:)   echo "Invalid option: -$OPTARG requires an argument" >&2 ;;
        esac
    done
    echo $((OPTIND -1)) "${args[@]}"
}

# Get number to shift plus set of arguments
extra_args1=($(parse_args "$@"))
shift ${extra_args1[0]}
unset extra_args1[0]

# Position dependent value
host="$1"
shift

# Get number to shift plus set of arguments
extra_args2=($(parse_args "$@"))
unset extra_args2[0]

# "${x[@]}" values are interpolated as quoted and vanish if fully empty
ssh "$host" "${extra_args1[@]}" "${extra_args2[@]}" "$@"

二重引用符を使用すると、"$@"個々の値自体が二重引用符として扱われるだけでなく、拡張する値がないと拡張全体が消える魔法を使用できます。同じ機能を使用して"${extra_args1[@]}"拡張を処理できます。"${extra_args2[@]}"

この方法の潜在的な欠点の1つは、それa=($(function))自体がワイルドカードの対象となるため、functionワイルドカードが返されると配列割り当ての一部に拡張されることですa。この問題に対する良い解決策はありません。

おすすめ記事