web-dev-qa-db-ja.com

オプションフラグが一貫していないbashスクリプト

以下のコードは、私が書いたスクリプトmweに基づくmweです。ここでは、通常の方法でフラグを指定しています。しかし、私は本当に奇妙な行動を見ています。 mwe -eまたはmwe -nと入力すると、引数がないと見なされ、no argが返されます。 mwe -kまたはmwe -iと入力すると、argType"-"ではないと見なされ、breakingが返されます。 #で終わる4行をコメント化すると、コードは期待どおりに機能します。これは、問題がwhileループによって引き起こされていることを示唆しています。誰かが何が起こっているのか説明してもらえますか?

#!/bin/bash
foo=0
argType=`echo "$1" | cut -c 1`
while [ 1 -gt 0 ] ;   #
    do   #
        if [ $# -eq 0 ] ; then
            echo no arg
            exit
        Elif [ "$argType" != "-" ] ; then
            #No more flags
            echo breaking
            break  #
        Elif [ "$1" = "-n"  ] ; then
            foo=1
            shift
        Elif [ "$1" = "-e"  ] ; then
            foo=2
            shift
        Elif [ "$1" = "-i"  ] ; then
            foo=3
            shift
        Elif [ "$1" = "-k"  ] ; then
            foo=4
            shift
        fi
done  #
echo This is foo:  $foo
3
Leo Simon

あなたの質問から、あなたが何を望んでいるかは明確ではありません!

とにかく、最後の引数に対応する数が欲しいようです

#!/bin/bash
foo=0;

while [[ $# -gt 0 ]]; do
    case "${1}" in
        '-n')
            foo=1;
            shift
        ;;
        '-e')
            foo=2;
            shift
        ;;
        '-i')
            foo=3;
            shift
        ;;
        '-k')
            foo=4;
            shift
        ;;
        *)
            echo "Invalid flag";
            exit 1;
        ;;
    esac
done

echo "This is foo: $foo"

代わりに、処理される前に引数を処理および検証するメカニズムが必要な場合は、次のようなものを使用できます

#!/bin/bash

inputf='';
outputf='';
text='';
format='';

while [[ $# -gt 0 ]];do
    case "${1}" in
        '-i')
            inputf="${2}";
            shift 2
        ;;
        '-o')
            outputf="${2}";
            shift 2
        ;;
        '-t')
            text="${2}";
            shift 2
        ;;
        '-f')
            format="${2}";
            shift 2
        ;;
    esac
done
2
Jonah

3行目は

_argType=$(printf "%s" "$1" | cut -c 1)
_

コメントで述べたように、echoは_-e_などの引数をオプションとして解釈するため、_-e_はcutに渡されません。さらに悪いことに、特別なケースとして、 オプション終了フラグ_--_はecho では使用できません。次に、printfが必要です。これは通常、とにかく優れています

bashにいるので、@ steeldriverの提案を採用して、パイプラインの代わりに_argType=${1:0:1}_(つまり、パラメーター1の場合は、char 0から開始して1 charを取得します)を使用できます。ただし、POSIXシェルでは使用できないことに注意してください。

特にネストの場合、後者は読みやすさに悪影響を与えるため、バックティックの代わりに$()を使用することもお勧めします。

最後に、シフトしていることに注意してください。そのため、その修正後でも_./myscript -e -i_を試行すると、最終的に_[ $# -eq 0 ]_がtrueになり、実行はexitによって終了します。多分それは意図されているかもしれませんが、そうではないかもしれませんが、最終的には最後のechoはトリガーされません。

6
Quasímodo