declare
とか typeset
、local
まわりの使い方について。
まず、declare
と typeset
は、シノニムなので、この 2 つの差異は考えなくて良いと思います。このため、ここでは declare
でひとまとめにして扱いたいと思います。
そういうわけで、declare
と local
さえ区別できれば良いんですが、あんま変わらないんですよね。。。
属性の付与
declare
と local
は、基本的に変数の宣言で使われますが、変数宣言とともに、その変数に対して属性を付与するときに使われます。
よく使われるのは、readonly のオプションですね。一度 -r
付きで宣言しておくと、その変数は readonly として扱われるようになり、それ以降で代入しようとするとエラーになります。
$ declare -r var="hoge" $ var="fuga" var: readonly variable
誤解されやすいのは、declare
による属性の付与は、後出しが可能ってことでしょうか。
Google の出している Shell Style Guide に readonly
を使った例が載っていますが、これ、declare
を使っても同じようなことができます。
zip_version="$(dpkg --status zip | grep Version: | cut -d ' ' -f 2)" if [[ -z "${zip_version}" ]]; then error_message else readonly zip_version fi
$ a="hoge" $ typeset -r a $ a="fuga" a: readonly variable $ echo $a hoge
「整数型」っていう属性を与えることもできます。整数型という属性を与えることにより、浮動小数点が代入できなくなったりします。
$ x=3.14 bash: 3.14: syntax error: invalid arithmetic operator (error token is ".14")
また、expr
や (( ))
とかを使わなくても、整数計算ができるようになったりします。
# declare -i を使った例 $ declare -i x $ x=3+4 $ echo $x 7 # declare -i を使わなかった例 $ z=3+4 $ echo $z 3+4
ただ、この手の計算結果の格納は、分かりにくいので使わない気がします。
上記の例だと、x
に文字列を代入しようとしたら計算結果が格納されているわけですが、前掲の通り、浮動小数点を代入しようとしたらエラーになるのは、あまり整合性が取れているとは思えないんですよね…。
この他、変数型が array であるとか、そういう属性を付けるときにも利用されたりします。
スコープ
というわけでスコープの話がでてくるんですが、local
はわかりやすくて、その名前の通り「ローカル変数」を宣言できます。
Bash スクリプトのスタイルガイドは、結構 local
使えってところが多いですね。Google の Shell Style Guide もそうですし、以下の Defensive BASH Programming でも同様のことが言われています。
change_owner_of_file() { local filename=$1 local user=$2 local group=$3 chown $user:$group $filename }
HugeDomains.com より引用
スコープの話といえば、local
の専売特許みたいなところがありますが、じつは typeset
でもスコープの概念が導入されます。
foo (){ declare FOO="bar" } bar (){ foo echo $FOO } bar # Prints nothing.
9.2. Typing variables: declare or typeset より引用
まぁ local
の場合は、グローバル空間で宣言しようとするとエラーになるので、そのあたりは違いますね。
$ local p bash: local: can only be used in a function $ typeset p