getoptsにオプションが指定されていない場合のデフォルトオプションの実行

getoptsにオプションが指定されていない場合のデフォルトオプションの実行

私はチュートリアルに従いました。ここ使用方法を学びますgetopts。ユーザーが提供したすべてのオプションを正しく実行できます。さて、私はオプションが提供されていないときにデフォルトのオプションを実行したいと思います。

たとえば、

while getopts ":hr" opt; do
    case $opt in
        h )
            show_help;
            exit 1
            ;;
        r )
          echo "Default option executed"
          ;;
    esac
done

したがって、ユーザーがまたはを指定した場合は-hその-rコマンドを実行する必要があります(はい)、これらのオプションが指定されていない場合は-rデフォルトで実行する必要があります。これを達成する方法はありますか?

修正する

cas's提案を試して、それを*)私のgetopts機能に統合しましたが、何も起こらないようです。

while getopts ":hr" opt; do
    case $opt in
        h )
            show_help;
            exit 1
            ;;
        r )
          echo "Default option executed"
          ;;

        \? )
          echo error "Invalid option: -$OPTARG" >&2
          exit 1
          ;;

        : )
          echo error "Option -$OPTARG requires an argument."
          exit 1
          ;;

        * )
          echo "Default option executed"
          ;;
    esac
done

このコードに問題がありますか?

答え1

解析するオプションがないとステートメントはcase実行されないため、ステートメントにデフォルトオプションを追加しても役に立ちません。getoptsシェル変数を使用して、どのくらいのオプションを処理しているかを確認できますOPTIND。からhelp getopts

Each time it is invoked, getopts will place the next option in the
shell variable $name, initializing name if it does not exist, and
the index of the next argument to be processed into the shell
variable OPTIND.  OPTIND is initialized to 1 each time the shell or
a shell script is invoked.

したがって、OPTIND1の場合、オプションは処理されません。ループの後に以下を追加しますwhile

if (( $OPTIND == 1 )); then
   echo "Default option"
fi

答え2

whileオプションが指定されていない場合、Bashのgetoptsは$ optを "?"に設定してループを終了します。スクリプトでこの状況を確認するには、次のようなループifの後に句を追加します。while

if [ "$opt" = "?" ]
then
  echo "Default option executed (by default)"
fi

参考までに以下を参照してください。Bourne Shell 組み込み関数

答え3

getoptsループを使用して渡された引数に基づいて変数を設定します。次に、次の変数に対処します。

#!/bin/sh

# Defaults:
do_help=0
do_r=0

while getopts "hr" opt; do
    case $opt in
        h) do_help=1 ;;
        r) do_r=1    ;;
        *) echo 'Error in command line parsing' >&2
           exit 1
    esac
done

if [ "$do_help" -eq 1 ]; then
    show_help
    exit
fi

printf 'Default option executed (r=%d)\n' "$do_r"

私はゼロ以外の終了状態(助けを求めるのはエラーではありません)を使用するのではなく、使用時に-h(失敗しない限り)コードを正常に終了することを選択しました。show_help

実行してください:

$ sh script.sh -r
Default option executed (r=1)
$ sh script.sh
Default option executed (r=0)
$ sh script.sh -h
script.sh[24]: show_help: not found

これは、コマンドライン解析コードを残りのスクリプトロジックから分離するという利点があります。

また、実際の解析ループを短く保ちながら、ループ後に基本的な健全性チェックを実行できます。たとえば、

# command line parsing loop above here

if [ "$do_help" -eq 1 ] && [ "$do_r" -eq 1 ]; then
    echo 'Options -h and -r are mutually exclusive' >&2
    exit 1
fi

# code that acts on user-supplied options below

答え4

私が知る限り、rは引数を期待しません。論理的には、rは何が起こっても同じように実行されます。

getopts句からr関連のコマンドを取得して実行します。私はこれがあなたの要件に十分であると信じています。つまり、「done」ステートメントの後にechoステートメントを配置します。

互換性やその他の理由でrが必要な場合は、getoptsでrをスタブに保つことができます。

0に設定された変数をスイッチとして追加することもできます。 r以外のオプションを選択すると、変数を1に変更する行があります。ステートメントが完了したら、「変数がゼロの場合はデフォルトのコマンドを実行します」と書くことができます。


私はCasの答えが一番良いと思います。コメントしたいのですが、権限がありません。私は彼のアイデアに基づいています。これはCasが提案したものと同じですが、1つのコマンドしかありません(したがって2つの同じコマンドがあるため、後で間違いを起こすことはありません)。

DEF="Default command executed"
while getopts ":hr" opt;
   do case $opt in 
     h) show_help; 
        exit 1 ;; 
     r) echo "$DEF" ;; 
     *) echo "$DEF" ;; 
  esac
done

関連情報