[シェルスクリプト] 未初期化と空文字列で初期化の違い

自前で動かすデーモンとかが増えてきたので、CentOSの/etc/init.d/functionsをまともに理解しとこうと思って読んでいると、以下のようなコードが見つかりました。

status() {
	local base pid lock_file= pid_file=

	# Test syntax.
	if [ "$#" = 0 ] ; then
		echo $"Usage: status [-p pidfile] {program}"
		return 1
	fi
	...

4つの変数が宣言されていて、そのうちbaseとpidは未初期化、残りの2つは空文字列で初期化されています。まさか/etc/init.d/functionsのような枯れきっているコードにミスなんかは残ってないと思ったので調べてみました。

とりあえず以下のようなコードを走らせてみました。

func() {
    local a b=

    echo "a is $a, length is ${#a}"
    echo "b is $b, length is ${#b}"
}
func

結果は以下のようになり、違いはわかりませんでした。

a is , length is 0
b is , length is 0

そもそもシェルスクリプトに慣れてない事もあり、色々検索してみても答えが見つからなかったので、久々にStackOverflowで質問したところ、見事に解答をもらえました。結論だけ書くと下記コードを走らせると違いが分かります。なおbash-3.xまではバグがあったようで、正常に動作するのはbash-4.xからだということです。

x() {
    local a b=

    echo ${a-X}
    echo ${b-X}
}

上記コードの結果が以下になります。未初期化変数aに対してはXが、初期化済みの変数bに対しては空行が出力されます。

X
 

今まで知らなかったのですが、シェルスクリプトでは上記のような変数展開が可能で、aが未初期化の場合はXで代用されるという式です。というわけで未初期化変数と空文字列で初期化された変数の違いがあるという事はわかりました。ただどのように使い分けられているのかはまだ分かりません。どなたかご存知でしたら教えてください。

あと初めてbashのマニュアルを見ましたが、かなりボリュームがあってビックリしました。シェルスクリプト奥が深そうです。あとPerl習得時に、この覚えにくい特殊変数群はどっから来たのかと思いましたが、シェルスクリプト由来なんですね。黒魔術にもほどがあります。

Leave a Reply

Your email address will not be published. Required fields are marked *