12

私はそれgetoptがクロスプラットフォームではないことを知りました(特にFreeBSDとLinuxの場合)。この問題の最善の回避策は何ですか?

4

4 に答える 4

30

コマンドには、基本的に2つのバージョンがありますgetopt。元のバージョンとGNU拡張バージョンです。GNU拡張バージョンは、元のバージョンと下位互換性があるため、元のバージョンの機能のみを使用する場合は、両方で機能します。

利用可能なgetoptのバージョンを検出します

使用可能なバージョンを検出し、GNU拡張バージョンが使用可能な場合は拡張機能を使用し、GNU拡張バージョンが使用できない場合は元の機能に制限することができます。拡張バージョンには、-T使用可能なバージョンをテストするためのオプションがあります。

getopt -T > /dev/null
if [ $? -eq 4 ]; then
    # GNU enhanced getopt is available
    set -- `getopt --long help,output:,version --options ho:v -- "$@"`
else
    # Original getopt is available
    set -- `getopt ho:v "$@"`
fi

getopts移植性が高いため、代わりに組み込みのシェルコマンド(「s」を使用)の使用を検討してください。ただし、getopts長いオプションはサポートされていません(例--help)。

長いオプションが好きな場合getoptは、上記のテストを使用して、のGNU拡張バージョンgetoptが利用可能かどうかを確認してください。拡張バージョンが利用できない場合、スクリプトは、元のバージョンgetopt(長いオプション名と空白のサポートなし)を使用するか、getopts(長いオプション名をサポートしない)を使用するように正常に機能を低下させる可能性があります。

GNU拡張getoptを適切に使用する

空白を含む引数を適切に処理するためにGNU拡張バージョンを取得するのは難しいです。方法は次のとおりです。

ARGS=`getopt --long help,output:,verbose --options ho:v -- "$@"`
if [ $? -ne 0 ]; then
  echo "Usage error (use -h for help)" >&2
  exit 2
fi
eval set -- $ARGS

# Parameters are now sorted: options appear first, followed by --, then arguments
# e.g. entering: "foo bar" -o abc baz -v
#      produces: -o 'abc' -v -- 'foo bar' 'baz'

秘密は"$@"、二重引用符が非常に重要な場所(1行目)とevalsetコマンド(6行目)に使用することです。

したがって、によって発生したエラーgetoptを検出して処理できるため、への呼び出しは、ARGS変数によってリンクされた2つを使用してとはgetopt別に実行されます。eval

完全な実例

PROG=`basename $0`

getopt -T > /dev/null
if [ $? -eq 4 ]; then
  # GNU enhanced getopt is available
  ARGS=`getopt --name "$PROG" --long help,output:,verbose --options ho:v -- "$@"`
else
  # Original getopt is available (no long option names, no whitespace, no sorting)
  ARGS=`getopt ho:v "$@"`
fi
if [ $? -ne 0 ]; then
  echo "$PROG: usage error (use -h for help)" >&2
  exit 2
fi
eval set -- $ARGS

while [ $# -gt 0 ]; do
    case "$1" in
        -h | --help)     HELP=yes;;
        -o | --output)   OUTFILE="$2"; shift;;
        -v | --verbose)  VERBOSE=yes;;
        --)              shift; break;; # end of options
    esac
    shift
done

if [ $# -gt 0 ]; then
  # Remaining parameters can be processed
  for ARG in "$@"; do
    echo "$PROG: argument: $ARG"
  done
fi

echo "$PROG: verbose: $VERBOSE"
echo "$PROG: output: $OUTFILE"
echo "$PROG: help: $HELP"

この例は、 https://gist.github.com/hoylen/6607180からダウンロードできます。

getoptsに関するウィキペディアのエントリの比較表は、さまざまな機能を比較しています。

于 2010-11-29T01:29:59.333 に答える
15

getopts(「s」を付けて)使用します。

Bash FAQ 35によると:

util-linuxのバージョンであり、詳細モードを使用している場合を除き、getopt(1)は使用しないでください。getoptは、空の引数文字列、または空白が埋め込まれた引数を処理できません。それがかつて存在したことを忘れてください。

POSIXシェル(およびその他)は、代わりに安全に使用できるgetoptsを提供します。

于 2010-04-28T10:30:31.863 に答える
1

の基本的な構文getoptはクロスプラットフォームです。

getopt vi: -v -i 100 file
于 2010-04-28T09:14:01.817 に答える
1

Bashの組み込みgetopts関数を使用して、短いオプションと長いオプションを移植可能に解析できます。以下を参照してください。

bashシェルスクリプトでgetoptsを使用して、長いコマンドラインオプションと短いコマンドラインオプションを取得する

于 2011-10-07T11:50:52.827 に答える