シェルスクリプトにヘルプメソッドを追加するにはどうすればよいですか?


回答:


173

これがbashの例です:

usage="$(basename "$0") [-h] [-s n] -- program to calculate the answer to life, the universe and everything

where:
    -h  show this help text
    -s  set the seed value (default: 42)"

seed=42
while getopts ':hs:' option; do
  case "$option" in
    h) echo "$usage"
       exit
       ;;
    s) seed=$OPTARG
       ;;
    :) printf "missing argument for -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
   \?) printf "illegal option: -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
  esac
done
shift $((OPTIND - 1))

これを関数内で使用するには:

  • "$FUNCNAME"代わりに使用$(basename "$0")
  • local OPTIND OPTARG呼び出す前に追加getopts

1
関数内でこれを試していますが、関数を実行しようとすると、「basename:invalid option-'b'」というエラーが表示されます。basename先頭のダッシュで「-bash」を渡そうとしているようです。
モーガンエステス2013

5
関数を使用し"$FUNCNAME"ないでください"$0"。また、追加local OPTIND OPTARG
glenn jackman 2013

ありがとう。FUNCNAME動作します。私はすべての機能を1つのファイルに収めているので、他の人に役立つものに拡張するのに最適です。
モーガンエステス2013

5
@sigur、それを使用する"$usage" すべての場所を引用しください。
グレンジャックマン16

1
何のshift $((OPTIND - 1))ためですか?
hpaknia

45

シェルスクリプトの最初の引数は変数として使用できる$1ため、最も簡単な実装は次のようになります。

if [ "$1" == "-h" ]; then
  echo "Usage: `basename $0` [somestuff]"
  exit 0
fi

しかし、anubhavaが言ったこと。


おかげ@MarkBooth、タイプミスを修正(プラス引用符でラップすることによって改善)
SEB

変数の不適切
JREAM

2
はい、ただしOPはbashを指定しておらず[、POSIX準拠のバージョンです。
2017年

注-内部で使用functionexit 0するreturn場合関数の実行後にシェルを終了したくない場合は、と置き換える必要があります。(私は以前にそれをやったことがある😂)
イルミネーター

29

これは、VNCサーバーを起動するために使用する部分です

#!/bin/bash
start() {
echo "Starting vnc server with $resolution on Display $display"
#your execute command here mine is below
#vncserver :$display -geometry $resolution
}

stop() {
echo "Killing vncserver on display $display"
#vncserver -kill :$display
}

#########################
# The command line help #
#########################
display_help() {
    echo "Usage: $0 [option...] {start|stop|restart}" >&2
    echo
    echo "   -r, --resolution           run with the given resolution WxH"
    echo "   -d, --display              Set on which display to host on "
    echo
    # echo some stuff here for the -a or --add-options 
    exit 1
}

################################
# Check if parameters options  #
# are given on the commandline #
################################
while :
do
    case "$1" in
      -r | --resolution)
          if [ $# -ne 0 ]; then
            resolution="$2"   # You may want to check validity of $2
          fi
          shift 2
          ;;
      -h | --help)
          display_help  # Call your function
          exit 0
          ;;
      -d | --display)
          display="$2"
           shift 2
           ;;

      -a | --add-options)
          # do something here call function
          # and write it in your help function display_help()
           shift 2
           ;;

      --) # End of all options
          shift
          break
          ;;
      -*)
          echo "Error: Unknown option: $1" >&2
          ## or call function display_help
          exit 1 
          ;;
      *)  # No more options
          break
          ;;
    esac
done

###################### 
# Check if parameter #
# is set too execute #
######################
case "$1" in
  start)
    start # calling function start()
    ;;
  stop)
    stop # calling function stop()
    ;;
  restart)
    stop  # calling function stop()
    start # calling function start()
    ;;
  *)
#    echo "Usage: $0 {start|stop|restart}" >&2
     display_help

     exit 1
     ;;
esac

スタートストップリスタートを別のケースに配置したのは少し奇妙ですが、うまくいくはずです。


-dに空のオプションを指定した場合。無限ループになりませんか?
zerobane 2016年

17

簡単なシングルオプションソリューションの場合は、 if

チェックするオプションが1つしかなく、それが常に最初のオプション($1)である場合、最も簡単な解決策はifテスト([)を使用することです。例えば:

if [ "$1" == "-h" ] ; then
    echo "Usage: `basename $0` [-h]"
    exit 0
fi

posixの互換性=も同様に機能することに注意してください==

なぜ引用$1

$1引用符で囲む必要がある理由は、存在しない$1場合、シェルは実行を試みてif [ == "-h" ]失敗するから==です。

$ [ == "-h" ]
bash: [: ==: unary operator expected

より複雑な用途getoptgetopts

提案 によって 他人引数を受け入れるためにあなたのオプションを単一の単純なオプションよりも多く持っている、または必要な場合は、その後、あなたは間違いなく使用しての余分な複雑さのために行く必要がありますgetopts

クイックリファレンスとして、私は60秒のgetoptsチュートリアルが好きです。

getopt組み込みのシェルの代わりにプログラムを検討することもできますgetopts。それは長いオプションの使用を可能にし、オプションの後に非オプションの引数(例えばfoo a b c --verbose、単にではなくfoo -v a b c)。このStackoverflowの回答は、GNUの使用方法を説明していますgetopt

jeffbyrnesさんは、元のリンク停止したと述べましたが、ありがたいことに、バックマシンがアーカイブした方法です。


ありがとう!私はgetoptsを1年間楽しく使っていますが、getoptについても見ていきます。
tttppp

1
悲しいことに、60秒のgetoptsチュートリアルへのリンクは無効になっています。bashcurescancer.comはもうないようです。ここにリンクがありますWayback Machineのバージョンとおりです。
jeffbyrnes 2014年


-1

あなたはこれのためにケースを使うことができると思います...

case $1 in 
 -h) echo $usage ;; 
  h) echo $usage ;;
help) echo $usage ;;
esac
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.