引数を保持した特殊変数をループ処理で参照する - Linux シェルスクリプト プログラミング

PROGRAM


引数を保持した特殊変数をループ処理で参照する

Linux シェル (sh) では、コマンドや関数の引数として渡した値は、順番に "$1", "$2", "$3" といった特殊変数に渡されます。

この特殊変数を、プログラムのループ内などで任意に参照したい場合には "eval" を用いて次のようにして、参照することが可能です。

# たとえば "$3" を取得したいとします。

INDEX=3

 

# 'echo $3' という文字列を組み立てて、それを eval で実行すると、その結果が得られます。

VALUE=$(eval echo '$'${INDEX})

このようにすることで、INDEX で指定した番号の特殊変数の値を参照して VALUE 変数に格納することができました。

 

引数の有無をチェックしながら、各引数の値を予め定めた大域変数に格納する

たとえば、INFO_PARAMS 配列に格納されている変数名に、コマンドの引数として渡された値を順に格納していくプログラムを考えます。

INFO_PARAMS には、大域変数名が必要な数だけ格納されていて、もしその大域変数名が "[ ]" で括られていた場合には、その引数は省略可能という意味を持たせます。逆に "[ ]" で括られていない変数は、引数が指定されていないときには、使用方法を表示してプログラムを終了するようにします。

このようなことは、次のようなプログラムで、実現することができました。

# 例えば、次の引数が指定されることを期待します。

 

## 1 番目の引数 "TARGET" は必須です。

## 2 番目の引数 "BRANCH" は必須です。

## 3 番目の引数 "START_POINT" は省略可能です。

 

INFO_PARAMS=("TARGET" "BRANCH" "[START_POINT]")

 

このとき、次のようなプログラムを用意して、引数のチェックと INFO_PARAMS で指定した名前の大域変数への代入を行ってみます。

# 便宜上、必須の引数が指定されていなかった場合に、コマンドの使用方法を表示する関数を用意しておきます。

show_usage()

{

# スクリプト名に続いて INFO_PARAMS に指定されている値を列挙しています。

echo "Usage: $0 ${INFO_PARAMS[*]}"

echo

}

# 引数の参照番号とエラーコードを初期化します。

INDEX=0

ERRORCODE=0

 

# 期待している引数の配列数を PARAM_COUNT に格納しています。

PARAM_COUNT=${#INFO_PARAMS[*]}

 

# 期待している引数全てをチェックして、同名の大域変数に値を確保します。

while [ "${INDEX}" -lt "${PARAM_COUNT}" ]

 

do

# 期待している引数のひとつを取り出しています。

PARAM="${INFO_PARAMS[$INDEX]}"

 

# 期待する引数名が [ ] で括られている場合は、"" を、そうでなければ引数名を設定しています。

PARAM_OPTIONAL="${PARAM#\[*\]}"

 

# 対応する実際の引数(例えば 1 番目なら "$1")を取り出します。

PARAM_INDEX="$((INDEX + 1))"

PARAM_VALUE=$(eval echo '$'${PARAM_INDEX})

 

# 期待する引数名が [ ] で括られていれば、それを取り除いて引数名だけにします。

PARAM_NAME="${PARAM#\[}"

PARAM_NAME="${PARAM_NAME%\]}"

 

# '引数名=引数に渡された値'という文字列を作成して eval でそれを実行し、期待する引数で指定した名前の大域変数へ、渡された値を格納しています。

eval ${PARAM_NAME}=\"${PARAM_VALUE}\"

 

 

# 期待する引数が [ ] で括られていないのに、実際の値が空だった場合には ERRORCODE=1 とします。

if [ "${PARAM_OPTIONAL}" != "" -a "${PARAM_VALUE}" == "" ]

then

ERRORCODE=1

fi

 

# 次の期待する引数を照査します。

INDEX=$((INDEX + 1))

done

 

# 全ての期待する引数の照査が終わった段階で ERRORCODE が 0 以外になっている場合には、プログラムを終了します。

if [ "${ERRORCODE}" -ne "0" ]

then

# このとき、あらかじめ作成しておいた、コマンド使用方法のメッセージを画面に表示しておきます。

show_usage

exit ${ERRORCODE}

fi

このようなプログラムを作成しておいて、シェルスクリプトの冒頭で INFO_PARAMS に期待する引数をセットしてから、このプログラムを読み込むことで、引数のチェックと大域変数への格納を、簡単に行うことができるようになりました。

たとえば、このスクリプトを "./functions" という名前で保存した場合には、スクリプトの冒頭で次のようにして使うことができます。

INFO_PARAMS=("SRC" "DST" "[DST_NAME]")

 

. ./functions

 

 

# 以下で、${SRC} や ${DST}、${DST_NAME} を使用して、スクリプトを記述して行きます。

 

このようにすることで、引数のチェックと大域変数への格納が終わった状態で、スクリプトを記載して行くことができます。

"$1" とか "$2" とかを分かりやすい変数名に格納する手間も省けますし、必須の引数が指定されなかった場合などにはスクリプトを中断してコマンドの使用方法が表示されるので、なかなか便利な感じになりました。


[ もどる ]