0

オプション文字列 ":a:b" を使用して Bash スクリプトを実行getoptsしていて、次のコマンド ライン パラメーターを指定するとします。

./script.sh -a foo bar -b bar zappo

「foo」のインスタンスは、オプションの予期される引数ですがa、オプションbには予期される引数がありません。ただし、「bar」のインスタンスと「zappo」のインスタンスの両方は、 では受け入れられませんgetopts。を実行した後getopts、受け入れられないすべての引数のリストを含む変数をエコーするにはどうすればよいですか? 「bar bar zappo」というリストを作成するにはどうすればよいですか? ありがとう!

便利なコードを次に示します。

#!/bin.bash
option_string=":a:b"
unexpected_parameters=""
OPTIND=1
while getopts "${option_string}" options; do
    case ${options} in
        a)
            echo "-a triggered with parameter ${OPTARG}" >&2 # output to STDERR
            ;;
        b)
            echo "-b triggered" >&2 # output to STDERR
            ;;
        \?)
            echo "invalid option: -${OPTARG}" >&2 # output to STDERR
            ;;
    esac
    #<insert code magic... unexpected_parameters="${unexpected_parameters} "$(MAGIC)"">
done
echo "unexpected parameters: ${unexpected_parameters}"
4

1 に答える 1

1

getopts最初の非オプション引数で処理を停止します。これが Posix スタイルの引数処理です。Posix スタイルの引数処理では、コマンドを指定すると

utility -a foo bar -b bar zappo

utility-bコマンドライン フラグとして解釈されません。-aが引数を取る場合bar、 が最初の位置引数になり、さらに 3 つの位置引数 、-b、が存在barzappoます。

GNU は、フラグ オプションをコマンド ラインのどこにでも配置できるように、コマンド ライン引数を並べ替えることによってこの構文を拡張します。ただし、環境変数を設定するPOSIXLY_CORRECTと、GNU ユーティリティは (ほとんどの場合) 通常の Posix ユーティリティのように動作します。GNU バージョンの Posix C ライブラリ関数getopt(3)(およびgetopt_long(3)) は、デフォルトで GNU 構文を使用し、POSIXLY_CORRECT環境変数にも適切に反応します。

ただし、bashgetoptsビルトインは厳密に Posix スタイルです。したがって、あなたの場合、 with getopts ":a:b"、ループは for flag awith argumentで1回だけ実行されますfoo。がgetopts終了OPTINDすると、最初の未使用のコマンドライン引数3(この場合はbar) のインデックスが設定されます。

getoptsGNU スタイルのオプション処理で使用する場合は、自分で並べ替えを行う必要があります。たとえば、次のようなことができます。

# Positional arguments are not necessarily unexpected; in fact, they are usually
# expected. So I accumulate them here in a bash array
positional=()
while (($#)); do
  # If you really wanted to do GNU style processing, you'd need to special case
  # '--' and "long options" starting with '--'. Here, I just do the simplest
  # thing, which is to pass anything that vaguely looks like an optional argument
  # (starts with a -) to getopts.
  if [[ $1 = -* ]]; then
    # Grab some options:
    while getopts "$option_string" option; do
      case $option in
        a) ... ;;
        # etc.
      esac
    done
    # get rid of whichever options we've handled and reset OPTIND
    shift $((OPTIND - 1))
    OPTIND = 1
  else
    # Accumulate and ditch the positional argument:
    positional+=("$1")
    shift
  fi
done

または、GNU 実装の を使用することもできますgetopt(1)。これは、すべての作業を自動的に行いますが、インターフェースが少し面倒になります。(少なくとも、私はそれが面倒だと思いますが、YMMV.)

于 2013-12-27T01:05:25.517 に答える