Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What is going on with this article?

More than 3 years have passed since last update.

@TsutomuNakamura

getopt(GNU/Linux, BSD) かgetopts(bash builtin) かで迷わない、bash のオプション解析

bash スクリプトでオプション解析を行う場合の悩み

bash でスクリプトでオプション解析を行う時に、getopt(GNU/Linux, BSD) とgetopts(bash ビルトイン)を利用することができますが、以下のような悩みがあります。

  • getopt

    • GNU/Linux 版とBSD 版で挙動が違う
    • GNU/Linux 版ではロングオプションが利用できるがBSD 版ではできない
    • GNU/Linux 版では引数(arg)のあとにオプションを置いても引数とオプションを分けて解析できるがBSD 版ではできない
  • getopts

    • bash であれば、あらゆるOS 上で利用できる
    • ロングオプションは利用できない
    • 引数のあとにオプションを置いても引数とオプションを分けて解析できない

上記の内容を考慮して、bash で少し複雑なオプション解析を必要とするスクリプトを組む場合にはgetopt(GNU/Linux) を使用したいのですがそれを使用した場合、Mac 等のLinux 環境外では利用できず不便なものとなります。
であればbash 環境下であればあらゆるOS 上で使用できるgetopts を使用したいのですが、それではロングオプションへの対応や引数のあとにオプションを置いた場合に解析できない問題がつきまとってくることになります。

そこで、上記の問題を解決するためにbash 環境であれば共通的に利用できるgetopt(GNU/Linux) があればこの問題を解決できるのではないか!
ということでbash ビルトインとして、bash 環境であれば共通で使えるgetopts を使ってgetopt(GNU/Linux) を実現できるユーテリティを作成しました!という記事です。

リポジトリ

※Bash 3 系では正しく動きません

使い方

リポジトリのgetoptses.sh をロードしてgetoptses コマンド(getopt にses がついている)をgetopt(GNU/Linux) と同じように使用すれば良いだけです。
なお、getopt にはオプションが幾つかありますが、getoptses ではよく使われる-o, --options-l, --long オプションのみを実装しています。

gitcloneからgetoptsesのロード
$ git clone https://github.com/TsutomuNakamura/getoptses.git
$ cp getoptses/getoptses.sh /path/to/getoptses/
$ . /path/to/getoptses/getoptses.sh

もしくは直接getoptses.sh をロードすることもできます。

curlでgetoptsesのロード
$ . <(curl -Sso- https://raw.githubusercontent.com/TsutomuNakamura/getoptses/master/getoptses.sh)

オプション解析のサンプルスクリプトは以下のようになります。

getoptsesサンプル
#!/bin/bash

function main() {
    . /path/to/getoptses/getoptses.sh

    local options
    options=$(getoptses -o "ab:" --longoptions "long-a,long-b:,lonb-c" -- "$@")
    if [[ "$?" -ne 0 ]]; then
        echo "Invalid option were specified" >&2
        return 1
    fi
    eval set -- "$options"

    while true; do
        case "$1" in
        -a | --long-a )
            echo "-a, --long-a"
            shift
            ;;
        -b | --long-b )
            echo "-b, --long-b: $2"
            shift 2
            ;;
        --long-c )
            echo "--long-c"
            shift
            ;;
        -- )
            shift
            break
            ;;
        * )
            echo "Internal error has occured" >&2
            return 1
            ;;
        esac
    done

    echo "args: $@"
    return 0
}

main "$@" || exit $?

参考

1
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
1
Help us understand the problem. What is going on with this article?