getoptとgetoptsは別の獣であり、人々は彼らが何をするかについて少し誤解しているようです。 getoptsは、bashコマンドラインオプションをループで処理し、見つかった各オプションと値を組み込み変数に順に割り当てる組み込みコマンドです。これにより、さらに処理することができます。 getoptただし、は外部ユーティリティプログラムであり、実際には、たとえばbash getopts、Perl Getoptモジュール、Python optparse/ argparseモジュールのようにオプションを処理しません。そのすべてgetoptすなわち、それはそれらを処理するシェルスクリプトのために簡単だそうことを、より標準的な形式に変換-んは、渡されたオプションは、正規化しています。たとえば、アプリケーションはgetopt次のものを変換する場合があります。
myscript -ab infile.txt -ooutfile.txt
これに:
myscript -a -b -o outfile.txt infile.txt
実際の処理は自分で行う必要があります。getoptオプションの指定方法にさまざまな制限を加える場合は、まったく使用する必要はありません。
- 引数ごとに1つのオプションのみを配置します。
- すべてのオプションは、位置パラメータ(つまり、非オプション引数)の前に配置されます。
- 値を持つオプション(
-o上記など)の場合、値は(スペースの後の)個別の引数として渡す必要があります。
getopt代わりになぜ使用するのgetoptsですか?基本的な理由は、GNUだけgetoptが長い名前のコマンドラインオプションをサポートしていることです。1(getoptLinuxでは、GNU がデフォルトです。MacOS XおよびFreeBSDには、基本的であまり役に立たないが付属していますgetoptが、GNUバージョンをインストールできます。以下を参照してください。)
たとえば、次のgetopt名前の私のスクリプトからのGNUの使用例はjavawrap次のとおりです。
# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD, you have to install this
# separately; see below.
TEMP=`getopt -o vdm: --long verbose,debug,memory:,debugfile:,minheap:,maxheap: \
-n 'javawrap' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
VERBOSE=false
DEBUG=false
MEMORY=
DEBUGFILE=
JAVA_MISC_OPT=
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-d | --debug ) DEBUG=true; shift ;;
-m | --memory ) MEMORY="$2"; shift 2 ;;
--debugfile ) DEBUGFILE="$2"; shift 2 ;;
--minheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MinHeapFreeRatio=$2"; shift 2 ;;
--maxheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MaxHeapFreeRatio=$2"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
これにより--verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"、類似または類似のオプションを指定できます。の呼び出しの効果は、getoptオプションを正規化して、--verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"より簡単に処理できるようにすることです。前後の引用符は"$1"、"$2"スペースを含む引数が適切に処理されるようにするために重要です。
最初の9行(行全体)を削除してもeval set、コードは機能します!ただし、コードでは、どのような種類のオプションが受け入れられるかが非常に厳しくなります。特に、上記の「正規」の形式ですべてのオプションを指定する必要があります。getoptただし、を使用すると、1文字のオプションをグループ化し--file foo.txtたり、長いオプションのより明確な形式を使用したり、or --file=foo.txtスタイルを使用したり、or スタイルを使用し-m 4096たり-m4096、オプションと非オプションを任意の順序で組み合わせたりすることができます。 getoptまた、認識されないオプションやあいまいなオプションが見つかった場合にもエラーメッセージを出力します。
注:実際には、基本とGNUの2つの完全に異なるバージョンがありgetopt、異なる機能と異なる呼び出し規約があります。2 Basic はかなり壊れています:長いオプションを処理しないだけでなく、引数または空の引数内の埋め込みスペースも処理できませんが、これは正しく行われます。上記のコードは基本的に動作しません。LinuxにはデフォルトでGNU がインストールされていますが、Mac OS XとFreeBSDでは個別にインストールする必要があります。Mac OS Xでは、MacPorts(http://www.macports.org)をインストールしてから、GNU (通常はに)をインストールし、それがシェルパスの先にあることを確認します。getoptgetoptgetoptgetoptsgetoptgetoptsudo port install getoptgetopt/opt/local/bin/opt/local/bin/usr/bin。FreeBSDにをインストールしmisc/getoptます。
独自のプログラムのサンプルコードを変更するためのクイックガイド:最初の数行のうち、すべてが「ボイラープレート」であり、を呼び出す行を除いて、同じままである必要がありますgetopt。後-nにプログラム名を変更し、後に短いオプションを指定し-o、後に長いオプションを指定する必要があります--long。値を取るオプションの後にコロンを置きます。
最後に、のset代わりにを含むコードが表示eval setされた場合、それはBSD用に書かれていgetoptます。eval setスタイルを使用するように変更する必要があります。これはgetopt、両方のバージョンので正常に機能しますが、プレーンsetはGNUでは正しく機能しませんgetopt。
1実際にはgetopts、ksh93は長い名前のオプションをサポートしていますが、このシェルはほど頻繁には使用されませんbash。ではzsh、を使用zparseoptsしてこの機能を取得します。
2技術的には、「GNU getopt」は誤称です。このバージョンは、GNUプロジェクトではなくLinux用に実際に作成されました。ただし、これはすべてのGNU規則に準拠しており、「GNU getopt」という用語が一般に使用されています(FreeBSDなど)。