Help us understand the problem. What is going on with this article?

Shell Script 引数のないオプションとパラメータを共存させる

More than 1 year has passed since last update.

Bashのプログラムで、引数のないオプションと引数を共存する方法がわからなかったので、整理してみる。

現象

実際こうなって欲しかったのだが

$ ./polling.sh https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130653 | 200
20190321-130655 | 200
^C
$ ./polling.sh -i https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130700 | 200 | https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130702 | 200 | https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130704 | 200 | https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-130705 | 200 | https://qiita.com/koara-local/items/04d3efd1031ea62d8db5

実際はこうなった

$ ./polling.sh -i https://qiita.com/koara-local/items/04d3efd1031ea62d8db5
20190321-125815 | N/A | -i
20190321-125816 | N/A | -i
20190321-125817 | N/A | -i
20190321-125818 | N/A | -i

どうやらオプションがパラメータとして認識されている様子。

問題の解決

問題は、getopts の書き方だった。知らなかったが、: が付いているのは、オプションの引数があるこをと示している。だから、今回のアプリは、引数がないので、それを取り除いた。

while getopts "ih" opt; do 
  case $opt in 
    i)
      hasUrl=true
      ;;
    h) 
      usage
      exit 0
      ;;
    \?)
     echo "Unknown option: -${OPTARG}" >&2
     exit 1
     ;;
  esac
done

ただし、これだと、$1を参照しても-i になるので、shiftコマンドで$1をシフトさせる。オプションのインデックスから1を引いた分だけシフトさせる。

shift $((OPTIND -1))

全体像

#!/bin/bash

declare -i duration=1
declare hasUrl=""
declare endpoint

usage() {
    cat <<END
    polling.sh [-i] [-h] endpoint

    Report the health status of the endpoint
    -i: include Uri for the format
    -h: help
END
}

while getopts "ih" opt; do 
  case $opt in 
    i)
      hasUrl=true
      ;;
    h) 
      usage
      exit 0
      ;;
    \?)
     echo "Unknown option: -${OPTARG}" >&2
     exit 1
     ;;
  esac
done

shift $((OPTIND -1))

if [[ $1 ]]; then
  endpoint=$1
else
  echo "Please specify the endpoint."
  usage
  exit 1 
fi 


healthcheck() {
    declare url=$1
    result=$(curl -I $url 2>/dev/null | grep HTTP/1.1)
    echo $result
}

while [[ true ]]; do
   result=`healthcheck $endpoint` 
   declare status
   if [[ -z $result ]]; then 
      status="N/A"
   else
      status=${result:9:3}
   fi 
   timestamp=$(date "+%Y%m%d-%H%M%S")
   if [[ -z $hasUrl ]]; then
     echo "$timestamp | $status "
   else
     echo "$timestamp | $status | $endpoint " 
   fi 
   sleep $duration
done
TsuyoshiUshio@github
プログラマ。自分の学習用のブログです。内容は会社とは一切関係ありません。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした