場所パラメータで書かれたスクリプトにコマンドラインオプションのサポートを導入するには?

場所パラメータで書かれたスクリプトにコマンドラインオプションのサポートを導入するには?

現在、次の場所パラメータで使用するスクリプトがあります。

./script.sh fname lname address

また、提供したくない引数をスキップできるように、このスクリプトを呼び出すときに一般的なコマンドラインオプションをサポートしたいと思います。

./script.sh -f fname -a address

fname唯一の必須パラメータです。

歴史的な理由と自動化のため、スクリプトは以前のバージョンと互換性があるはずです。

-f これまでの私の推測では、文字列(スペースで囲まれている)を見つけることです。

  • 見つかった場合、フラグを処理します。
  • それ以外の場合は順次処理
flags='(\ |^)-f\ '
if [[ $* =~ $flags ]]; then
while [ $# -ne 0 ]
do
    name="$1"
    case "$name" in
        -f)
            shift
            fname=$1
            ;;
        -l)
            shift
            lname=$1
            ;;
        -a)
            shift
            address=$1
            ;;
    esac
    shift
done
else
    fname=${1}
    lname=${2}
    address=${3}
fi

ただし、ここでは正規表現を使用してオプションを確認する必要がありますが、これは信頼できない可能性があります。

コマンドラインオプションと位置パラメータを組み合わせる基本的な方法はありますか?

ベストアンサー1

一般的なコマンドライン解析を実装するために使用されますgetopts。この解析がトリガされたら、この事実を追跡するためのフラグを設定します。標準getoptsループの後にフラグが設定されていない場合、前の動作が返されます。

以下のコードでは、フラグは変数ですnew_behavior

#!/bin/bash

# As written now, this should run without issues with
# /bin/sh too (there are no bash-isms in this code).

unset address
unset fname
unset lname

new_behavior=false

while getopts 'a:f:l:' opt; do
        new_behavior=true

        case $opt in
                a)
                        address=$OPTARG
                        ;;
                f)
                        fname=$OPTARG
                        ;;
                l)
                        lname=$OPTARG
                        ;;
                *)
                        echo 'Error in command line parsing' >&2
                        exit 1
        esac
done

shift "$(( OPTIND - 1 ))"

if ! "$new_behavior"; then
        # Fall back on old behavior.

        fname=$1;       shift
        lname=$1;       shift
        address=$1;     shift
fi

if [ -z "$fname" ]; then
        echo 'Missing mandatory argument "fname"' >&2
        exit 1
fi

# The rest is unimportant to the actual command line parsing code
# and only here for your information and for debugging.

printf 'fname="%s", lname="%s", address="%s"\n' \
        "$fname" "$lname" "$address"

if [ "$#" -gt 0 ]; then
        printf 'Extra argument: "%s"\n' "$@"
fi

ユーザーがスクリプトの最初の引数としてオプションを指定すると、新しい動作がトリガーされます。オプションが有効かどうかは重要ではありません。

以前の動作テスト:

$ ./script eff ell addr
fname="eff", lname="ell", address="addr"
$ ./script eff ell addr "hello world"
fname="eff", lname="ell", address="addr"
Extra argument: "hello world"
$ ./script eff
fname="eff", lname="", address=""
$ ./script
Missing mandatory argument "fname"
$ ./script eff -l ell
fname="eff", lname="-l", address="ell"

新しい動作をテストします。

$ ./script -a addr -l ell -f eff
fname="eff", lname="ell", address="addr"
$ ./script -a addr -f eff "hello world"
fname="eff", lname="", address="addr"
Extra argument: "hello world"
$ ./script -f eff "hello world"
fname="eff", lname="", address=""
Extra argument: "hello world"
$ ./script -l eff "hello world"
Missing mandatory argument "fname"
$ ./script -f eff -- -l ell -f "eff again"
fname="eff", lname="", address=""
Extra argument: "-l"
Extra argument: "ell"
Extra argument: "-f"
Extra argument: "eff again"

(最後の例では、オプションではない追加の引数はoptionsから分離されており、--2-l番目の引数はすべて-fオプションではありません。)

おすすめ記事