61

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

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

より良い方法はありますか?

注: switch/getopt のすべてのフラグを明示的にリストしたくありません。(この場合、そのようなものはスクリプト全体の半分以上になります。また、変数のセットを設定した場合の本体も)

4

8 に答える 8

79

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

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

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

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

于 2010-05-20T17:16:18.773 に答える
15

通常、これは 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この場合、他のオプションは変数を使用して構築されます。

于 2010-05-20T15:53:41.500 に答える
11

簡単なアプローチを取り、引数を繰り返し処理して、指定されたパラメーター ( -t、 など--therizinosaurus) と等しいかどうかをそれぞれテストすることができます。

それを関数に入れます:

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コマンド ラインの最後に配置できます (それが良いか悪いかには関係ありません)。


、考えれば考えるほど気になることがありました。

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

私の傾向は再利用を好む傾向にありますが、その意味を認識しておく必要があります。反対のアプローチは、恐れていたようにスクリプトの先頭でこれらの引数を 1 回解析し、解析の繰り返しを避けることです。
その switch ケースをカプセル化することもできます。これは、決定した大きさにすることができます (すべてのオプションをリストする必要はありません)。

于 2019-06-03T16:24:23.393 に答える
7

bash で getopt キーワードを使用できます。

http://aplawrence.com/Unix/getopts.htmlから:

getopt

これは、長い間使用されてきたスタンドアロンの実行可能ファイルです。古いバージョンには、引用符で囲まれた引数 (foo a "this won't work" 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
于 2010-05-20T15:50:33.097 に答える
1

代替案ではありませんが、改善策です。

if echo $* | grep -e "\b--flag\b" -q

単語の境界を探すと、実際にオプションが取得され、--flagどちら--flagstaffも取得されません--not-really--flag

于 2020-11-19T14:02:13.147 に答える