argbashでbashスクリプトのオプション引数を受け取る

この記事はShell Script Advent Calendar 2017の15日目の記事です。

bashスクリプトでオプション引数を処理したい時にcaseで処理したりすると思いますが、引数の処理をサポートするargbashというツールがありました。というわけで、試してみます。

argbashでは3種類の引数の形式を使用できます。オプション引数は-が2つのロングオプション形式です。例えば、--fooとかですね。

引数のタイプ argbashでの使い方
bool型。引数を受け取らないタイプ --bool-opt 名前
引数を受け取るタイプ --opt 名前
--で始まるオプションを使わないタイプ。rmコマンドのファイル名とかディレクトリ名みたいなタイプ --pos 名前

argbashの使いかとしてはargbash-initというツールでテンプレートを作って、argbashでシェルスクリプト化するのが基本のようです。また、bool型の引数の場合、--bool-opt fooとすると--fooと--no-fooという2個のオプションが作られます。後者の方は--fooを無効にするってことですね。

試しに--name 文字列という形の引数を受け取るような設定でコマンドを使うとこのような感じになります。

masami@saga:~/codes/argtest$ argbash-init --opt name
#!/bin/bash

# m4_ignore(
echo "This is just a script template, not the script (yet) - pass it to 'argbash' to fix this." >&2
exit 11  #)Created by argbash-init v2.5.0
# ARG_OPTIONAL_SINGLE([name], , [<name's help message goes here>])
# ARG_HELP([<The general help message of my script>])
# ARGBASH_GO

# [ <-- needed because of Argbash

echo "Value of --name: $_arg_name"

# ] <-- needed because of Argbash

この例では標準出力に出力してますが、パイプでargbashにデータを渡しても構いません。では、実行してみます。

masami@saga:~/codes/argtest$ argbash-init --opt name | argbash -o name.sh -
masami@saga:~/codes/argtest$ wc -l name.sh
82 name.sh
masami@saga:~/codes/argtest$ 

82行ほどのファイルができあがります。ヘルプ用に-h/--helpがサポートされています。自分で作った--nameオプションを使うと値が表示されます。あとは自分で弄っていく感じですね。

masami@saga:~/codes/argtest$ ./name.sh -h
<The general help message of my script>
Usage: ./name.sh [--name <arg>] [-h|--help]
        --name: <name's help message goes here> (no default)
        -h,--help: Prints help
masami@saga:~/codes/argtest$ ./name.sh --name foobar
Value of --name: foobar

このスクリプトのオプション引数はこのように解析されます。

parse_commandline ()
{
        while test $# -gt 0
        do
                _key="$1"
                case "$_key" in
                        --name)
                                test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
                                _arg_name="$2"
                                shift
                                ;;
                        --name=*)
                                _arg_name="${_key##--name=}"
                                ;;
                        -h|--help)
                                print_help
                                exit 0
                                ;;
                        -h*)
                                print_help
                                exit 0
                                ;;
                        *)
                                _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
                                ;;
                esac
                shift
        done
}

引数3パターン使ってみて、greeting引数には適当なメッセージ、to-upppercaseでname引数の大文字化をするようなことをしてみます。

masami@saga:~/codes/argtest$ argbash-init --pos name --opt greeting --opt-bool to-upppercase | argbash -o test.sh -                                                                                                

そして、test.shをちょろっと弄ります。

name=${_arg_name}
if [ ${_arg_to_upppercase} = "on" ]; then
    name=${_arg_name^^}
fi

echo "Value of --greeting: $_arg_greeting"
echo "to-upppercase is $_arg_to_upppercase"
echo "Value of name: ${name}"

これを実行するとこんなふうになります。

masami@saga:~/codes/argtest$ ./test.sh --greeting hello --to-upppercase foobar
Value of --greeting: hello
to-upppercase is on
Value of name: FOOBAR
masami@saga:~/codes/argtest$ ./test.sh --greeting hello --no-to-upppercase foobar
Value of --greeting: hello
to-upppercase is off
Value of name: foobar
masami@saga:~/codes/argtest$ ./test.sh --greeting hello  foobar
Value of --greeting: hello
to-upppercase is off
Value of name: foobar

argbashはオプションの解析部分・ヘルプメッセージ表示をサポートしてくれるので結構良いですね( ´∀`)bグッ!

シェルプログラミング実用テクニック

シェルプログラミング実用テクニック