ラベル bash の投稿を表示しています。 すべての投稿を表示
ラベル bash の投稿を表示しています。 すべての投稿を表示

2007年5月7日月曜日

getopt

概要

 getoptは主にシェルスクリプトでコマンドオプションを使いやすい形に変形するために使う。いくつか書式があるが、伝統的なgetoptでは以下のように使う。

$getopt optstring parameters
引数はoptstringとparamtersに分かれる。optstringにはオプションと認識する一文字を連続して書く。その文字の最後に:をつけた場合は、そのオプションはパラメータをとるという意味になる。parametersは、解析する引数を書く。

伝統的なコマンド使用例

 例えば ab:cとした場合は、-a -b -cをオプションとして認識し、-bオプションはパラメータをとることになる。出力の順番はオプションと必要があればそのパラメータがすべて出力され、'--'を出力後にどれでもないものが出力される。

$ getopt ab:c -a
-a --
上の例では、parametersが-aオプションのみなので-aと'--'が出力される。
$getopt ab:c -b
getopt: オプションには引数が必要です -- b
--
今度は-bオプションを指定したが、-bオプションには引数が必要となるためエラーとなる。
$ getopt ab:c -b aaa
-b aaa --
上記のように書くと、aaaが-bオプションの引数になるので正常に出力される。
$ getopt ab:c -b aaa -a bbb -c
-b aaa -a -c -- bbb
-aの後にbbbを書くと、-aは引数をとらないのでbbbはオプションでもオプションの引数でもないことになり、--の後ろに出力され、順番が入れ替わる。
$ getopt ab:c -b aaa -a -c -d
getopt: オプションが違います -- d
-b aaa -a -c --
-dはoptstringに定義されていないため、エラーとなる。

 このようにgetoptでオプション文字並びにオプションの引数チェックとオプション文字でもオプションの引数でもないものを後ろに並べかえてくれる。

拡張コマンド使用例

 GNUのgetoptの場合は以下のような書き方ができる。(他にもいくつか書き方があるが詳細はgetop(1)を参照のこと)

$getopt -o optstring -l longoptstring -- parameters
-oは短いオプションを上記と同じ形式で記述する。-lには、長いオプション名を','で区切りながら記述できる。また、短いオプションと同様に最後に':'をつけるとそのオプションは引数を取ることになる。paramtersで長いオプションは'--'で始まる。
$getopt -o ab:c -l dfg,hij: -- -a --dfg abc --hij aaa
-a --dfg --hij 'aaa' -- 'abc'
--dfgと--hijがオプションとして認識され、aaaは--hijの引数となる。また、この書式を使うとシェルでのメタ文字の展開を避けるため、オプションの引数とオプション文字でもオプションの引数でもないものはシングルクォートされて出力される。

シェルスクリプト利用例

 シェルスクリプトで使う場合は以下のようにして使う。

OPTIONS=`getopt -o ab:c --long dfg,hij: -- "$@"`
if [ $? != 0 ] ; then
 exit 1
fi
eval set -- "$OPTIONS"
while true; do
    case "$1" in
        -a)
        # -aのときの処理
        shift
        ;;
    -b)
        # -bのときの処理
        shift 2
        ;;
    -c)
        # -cのときの処理
        shift
        ;;
    --dfg)
        # --dfgのときの処理
        shift
        ;;
    --hij)
        # --hijのときの処理
        shift 2
        ;;
    --)
        shift
        break
        ;;
    *)
        echo "Internal error!" >&2
        exit 1
        ;;
    esac
done
# オプションでもオプションの引数でもないものの処理
$@はシェルスクリプトの位置パラメータ($1,$2,...)に展開されるので、それをgetoptにかけ、オプションとそのパラメータが先になるように並べ変える。その際、認識できないオプションがあったり、オプションのパラメータが存在しない場合はエラーとなる。その出力結果をもう一度「set -- 」で位置パラメータに入れ直す。ただし、シェルの特別な文字を展開しないように、$OPTIONSをダブルクォート("$OPTIONS")としてパラメータ展開を行っているため、evalとして実行する。(そうしないと、setのパラメータとして展開されるので、ひとつの単語とみなされ$1にまとめて設定されてしまう。evalをつけるとevalのパラメータとして展開された後、「set --」が実行されるため、スペース区切りでそれぞれ位置パラメータに設定される。)

■ 参考資料

Manpage of GETOPT
Manpage of BASH

2007年4月21日土曜日

bashの%パラメータ展開方法

bashの%と%%のパラメータ展開方法を調べる。
manには以下のようにある。

${parameter%word}
${parameter%%word}
        word が展開され、パス名展開の場合と同じようなパターンを作ります。このパタ
        ーンが parameter を展開した値の末尾の部分とマッチする場合、展 開 結 果 は
        parameter  を展開した値から最短一致パターン (‘‘%’’ の場合) または最長一
        パターン (‘‘%%’’ の場合) を取り除いたものになります。 parameter が @ ま
        は * である場合、パターンを削除する操作は全ての位置パラメータに順番に適用
        され、展開結果はリストとして得られます。 parameter が @ または * が添字に
        な っている配列変数である場合、パターンを削除する操作は配列の全ての要素に
        順番に適用され、展開結果はリストとして得られます。
この記述だと、何をいっているのかよくわからないので簡単なシェルスクリプトを書いて試してみた。
#!/bin/sh

dest="$1"
echo $dest
dest="${dest%/}" #末尾/を削除
echo $dest
dest="${dest%/*}" #末尾の/*を削除(最小一致)
echo $dest
dest="${dest%%/*}" #末尾の/*を削除(最大一致)
echo $dest
これを実行すると以下のようになる。
$ ./test.sh /aaa/bbb/ccc/
/aaa/bbb/ccc/
/aaa/bbb/ccc
/aaa/bbb

$ ./test.sh aaa/bbb/ccc/
aaa/bbb/ccc/
aaa/bbb/ccc
aaa/bbb
aaa
@や*は試していないが、なんとなく使い方はわかった。

2007年4月20日金曜日

bashコマンドオプション

シェルスクリプトを見ていたら、bash -eという記述があった。manで調べてもオプションには見つからない。試しにhelpオプションを実行してみたら、その中にも存在しないが、別のhelpがあるようだ。

$ bash --help
GNU bash, version 3.1.17(1)-release-(i486-pc-linux-gnu)
(省略)
Type `bash -c "help set"' for more information about shell options.
Type `bash -c help' for more information about shell builtin commands.

で、bash -c "helpset"を実行してみた。
set: set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
         -a Mark variables which are modified or created for export.
        -b Notify of job termination immediately.
        -e Exit immediately if a command exits with a non-zero status.
        -f Disable file name generation (globbing).
        -h Remember the location of commands as they are looked up. (省略)
これによると、-eはコマンドが失敗した場合はすぐ終了するというオプションであった。
先頭の行をみると、bashのsetという組み込みコマンドのオプションの説明であるようだ。もう一回manをみてみると、確かにオプションのところに書いてあった。
bash は以下のオプションを起動時に解釈します (組み込みコマンド set の説明で述べられている 1 文字のシェルオプションも使えます):

ということで、bashの起動オプションを調べるには、setの項も見る必要がある。ちなみにsetはbashのめちゃめちゃ長いmanの中でもかなり下の方にある。なので、JM Projectを活用してブラウザで見るか、先の「bash -c "help set"」を使用したほうが見やすい。

■ 参考資料

Manpage of BASH