web-dev-qa-db-ja.com

bashでコマンドラインフラグをチェックする正しい方法

スクリプトの途中で、コマンドラインで特定のフラグが渡されたかどうかを確認したいと思います。以下は私が望むことをしますが醜いようです:

if echo $* | grep -e "--flag" -q
then
  echo ">>>> Running with flag"
else
  echo ">>>> Running without flag"
fi

もっと良い方法はありますか?

注:私は明示的にしないでくださいスイッチ/ getopt内のすべてのフラグを一覧表示する必要があります。 (この場合、そのようなものはスクリプト全体の半分以上になります。varのセットを設定した場合の本体も)

43
BCS

あなたがやっていることの代替:

if [[ $* == *--flag* ]]

BashFAQ/035 も参照してください。

:これは、単純な部分文字列チェックであるため、--flags-offにも一致します。

通常、これはcaseステートメントで行われます。 git-repack スクリプトからの抜粋を次に示します。

while test $# != 0
do
    case "$1" in
    -n) no_update_info=t ;;
    -a) all_into_one=t ;;
    -A) all_into_one=t
        unpack_unreachable=--unpack-unreachable ;;
    -d) remove_redundant=t ;;
    -q) GIT_QUIET=t ;;
    -f) no_reuse=--no-reuse-object ;;
    -l) local=--local ;;
    --max-pack-size|--window|--window-memory|--depth)
        extra="$extra $1=$2"; shift ;;
    --) shift; break;;
    *)  usage ;;
    esac
    shift
done

これにより、短いフラグと長いフラグの両方を確認できることに注意してください。この場合、extra変数を使用して他のオプションが構築されます。

10
Kaleb Pederson

Getoptキーワードはbashで使用できます。

From http://aplawrence.com/Unix/getopts.html

getopt

これは、長い間使用されてきたスタンドアロンの実行可能ファイルです。古いバージョンでは、引用符で囲まれた引数(foo a "これは機能しません" c)を処理する機能がなく、このバージョンでは、ぎこちなく処理できます。最近のLinuxバージョンを実行している場合は、「getopt」でそれを実行できます。 SCO OSR5、Mac OS X 10.2.6およびFreeBSD 4.4にはない古いバージョンがあります。

「getopt」の簡単な使用法は、このミニスクリプトに示されています。

#!/bin/bash
echo "Before getopt"
for i
do
  echo $i
done
args=`getopt abc:d $*`
set -- $args
echo "After getopt"
for i
do
  echo "-->$i"
done
6
WhirlWind

単純なアプローチを取り、引数を反復処理して、指定されたパラメータ(-t)。

それを関数に入れます:

has_param() {
    local term="$1"
    shift
    for arg; do
        if [[ $arg == "$term" ]]; then
            return 0
        fi
    done
    return 1
}

…そして、それをテスト式の述語として使用します。

if has_param '-t' "$@"; then
    echo "yay!"
fi

if ! has_param '-t' "$1" "$2" "$wat"; then
    echo "nay..."
fi

空の引数を拒否する場合は、ループ本体の上部に出口点を追加します。

for arg; do
    if [[ -z "$arg" ]]; then
        return 2
    fi
    # ...

これは非常に読み取り可能であり、パターンマッチングや正規表現マッチングのように、誤検出を与えません。
また、フラグを任意の位置に配置できます。たとえば、-hコマンドラインの最後に(それが良いか悪いかに関係なく)。


but、それについて考えれば考えるほど、何かが私を悩ませました。

関数を使用すると、任意の実装(getoptsなど)を取得して再利用できます。カプセル化ルール!
しかし、コマンドを使用しても、この強さは欠陥になる可能性があります。何度も使用する場合は、毎回すべての引数を解析することになります。

私の傾向は再利用を支持する傾向ですが、その影響を認識している必要があります。反対のアプローチは、恐怖のように、スクリプトの先頭でこれらの引数を一度解析し、繰り返しの解析を回避することです。
それでも、スイッチケースをカプセル化できます。これは、あなたが決定した大きさになる可能性があります(オプションallをリストする必要はありません)。

4
Eliran Malka