shellの引数で処理を分ける方法


業務で覚えた知識を備忘録として記載していきます。

対象者

  • shellに興味のある人
  • 実行時の引数で処理を分けたい場合

先日業務でshellを書くことがあったのですが、調べてみると中々自分がやりたい内容が見つからなかったので、そんな人の一助になればと思ったのと単純に覚えた内容を忘れないために記事にしたいと思いました。

やりたいこと

  • shell実行時の引数で処理を分ける
  • 外部ファイルを読み込み情報を取得する
  • 取得した情報を変数として持ち活用する

使用コマンド if / while read LINE / AWK

if [ 条件 ] then [ 実行処理 ] fi
while read LINE (変数名)
do
  実行されるコマンド
done < [ ファイル名 ]
awk [ オプション ]  [ コマンド ]

環境

Linux

ディレクトリ構成

シンプルに実行するshellと読み取るファイルが同じ階層のケース。
shellを実行するとlist.csvを読み取り、引数に対応した値を取得する。
階層が複雑な場合はフルパス指定したり、プロパティファイルを作ったり変数にしたりして可読性とメンテナンス性を上げる。
下記はサンプルなので.confファイルも中身2行で用意。

home/
  ├ country.sh
  └ list.conf

ファイルの中身

list.conf
JPN,日本,東京,3
USA,アメリカ合衆国,ワシントンDC,1
CHN,中華人民共和国,北京,2
DEU,ドイツ連邦共和国,ベルリン,4
IND,インド,ニューデリー,5
・・・

shellの中身

country.sh
#!/bin/bush
#シェル名:country.sh
#処理概要:引数に与えた国の和名と首都、GDP何位かを表示します。
#引数:$1 国コード(アルファベット3桁)

#設定ファイル
CONF_FILE="/home/list.conf"

#1.開始メッセージ
echo "処理を開始します。"

#2.パラメータチェック
if [ $# -ne 1 ]
then
 #パラメータ数不正
 $echo "引数の国コードは1つ(3文字)にしてください。"
exit
fi
PARAM_IF_ID=$1

#3.定義ファイル取得
while read LINE
do
TOP_STR=`echo ${LINE:0:1}`
if [ ${TOP_STR} == "#" ]
  then
  # コメント行
  countinue
fi

#引数取得
IF_ID=`echo ${LINE} | awk -F, '{print $1}'`
  #引数判定
  if [ "${IF_ID}" = "${PARAM_IF_ID}" ]
    then
    #国名(和名)
    NAME=`echo ${LINE} | awk -F, '{print $2}'`
    #首都
    CAP=`echo ${LINE} | awk -F, '{print $3}'`
    #国内総生産ランキング
    GDP=`echo ${LINE} | awk -F, '{print $4}'`
    break
fi
done < ${CONF_FILE}

echo "選択した"${NAME}"の首都は"${CAP}"です。近年のGDPは世界"${GDP}"位でした。"
exit

shell実行引数をキーにlist.confファイルから情報を抽出する。
処理を実行するとメッセージが表示され、引数が1つ以外の場合はエラーを発して終了します。
決められた引数を受け取ると、list.confの2カラム目、3カラム目の値を$2/$3...に受け取っていく。
あとは内部の処理で受け取った引数を使うだけ。

引数が"JPN"の実行結果

$ bash country.sh JPN
処理を開始します
選択した日本の首都は東京です近年のGDPは世界3位でした

引数が"USA"の実行結果

$ bash country.sh USA
処理を開始します
選択したアメリカの首都はワシントンDCです近年のGDPは世界1位でした

引数なしの場合

$ bash country.sh
処理を開始します
引数の国コードは1つ(3文字)にしてください

解説という名の復習

引数をキーに.confファイルの中身を抽出する方法でした。
ポイントはwhile read LINEと awk を|を使って繋げた所です。
.confファイルの中身を一行ずつ取り出して変数に格納していて,(カンマ)区切りで記入されたファイルの中身を読み取っています。
この処理があるので.confファイル内に複数のパターンの定義が存在していても、引数をキーに使い分けることが出来ます。
今はA/Bパターンだけでも、今後C/D/E...と増えた際に.confファイルのみメンテすればshellの処理を変えずに対応が可能となりメンテナンス性が向上します。