Bashのビルトインコマンド `declare` の使い方紹介(変数のlocalスコープ)
またまた、以下のエントリの続き。
- シェルスクリプトサンプルコードでよく見かける typeset や declare ってなに?
- Bash のビルトインコマンド "declare" の使い方紹介(その1)
- Bash のビルトインコマンド "declare" の使い方紹介(その2:大文字小文字の自動変換)
- Bash のビルトインコマンド "declare" の使い方紹介(その3:読み取り専用)
※だんだんシリーズみたいになってきました(笑)
今回は 前回 の続きで、Bash における変数のスコープ(参照可能な範囲)について。
検証環境
$ bash -version
GNU bash, バージョン 5.0.2(1)-release (x86_64-apple-darwin18.2.0)
declare
コマンドで定義した変数は関数の中だけのいのち
読み取り専用の変数を定義するためには、declare -p
を使っても readonly
を使っても違いはなさそうというところまで確認しました。
$ declare -r A=a1
$ readonly B=b1
# `-p` オプションで変数がどのように定義されたものかを確認できます。
# 変数名を複数指定して、いっぺんに出力することもできます。
$ declare -p A B
declare -r A="a1"
declare -r B="b1"
Bash のビルトインコマンド "declare" の使い方紹介(その3) の終わりでも話したとおり、これは 関数の外部で変数が定義された場合 のみの話。
関数の内部で定義された変数の場合には事情が異なります。
関数の内部で定義された場合の両者の違いを見ていきましょう。
# 関数を作成
$ function f() {
declare -r C=c1
readonly D=d1
echo "f: C=$C D=$D"
}
# 関数の呼び出しを行っていないため、いずれの変数も値は空
$ echo "C=$C D=$D"
C= D=
# 関数を呼び出して、関数内の変数値を出力
$ f
f: C=c1 D=d1
# 関数の内部で代入したDの値は参照可能
$ echo "C=$C D=$D"
C= D=d1
# 変数は見つからない
$ declare -p C
bash: declare: C: 見つかりません
# 変数が見つかる
$ declare -p D
declare -r D="d1"
declare
で定義した変数は、関数の内部でしか参照できません。
local
コマンド
declare -r
と readonly
の関係と同じように、 declare
を使わずにローカルスコープの変数を定義することが可能です。 local
という Bash のビルトインコマンドを使います。
# 関数を作成
$ function f() {
declare -r C=c1
# ローカルスコープとして定義
local D=d1
# 読み取り専用
readonly D
echo "f: C=$C D=$D"
}
# 関数の呼び出しを行っていないため、いずれの変数も値は空
$ echo "C=$C D=$D"
C= D=
# 関数を呼び出して、関数内の変数値を出力
$ f
f: C=c1 D=d1
# 関数の内部で代入したDの値は参照可能
$ echo "C=$C D=$D"
C= D=
# 変数は見つからない
$ declare -p C
bash: declare: C: 見つかりません
# 変数は見つからない
$ declare -p D
bash: declare: D: 見つかりません
local
コマンドのみを使うことも可能だし、 readonly
コマンドのみを使うこともできます。local
コマンドと readonly
コマンドを組み合わせて使う場合には、順序が重要です。readonly
=> local
の順番で呼び出すことはできません。
$ function f() {
local X=1
readonly X
declare -p X
readonly Y=2
local Y
declare -p Y
}
$ f
declare -r X="1"
bash: local: Y: 読み取り専用の変数です
declare -r Y="2"
$ echo "X=$X Y=$Y"
X= Y=2
local
コマンドは関数の内でしか使うことはできません。
$ local Z=3
bash: local: 関数の中でのみ使用できます
呼び出し順序やら関数内部でしか使えないやらでややこしいので、 readonly
コマンドや local
コマンドを覚えるよりも、 declare
の使い方を覚えてしまったほうが良いと思います。
declare
コマンドを使って、予め関数の外で定義した変数は関数の中でどう見える?
これは問題なく参照できます。
# 関数の外で定義
$ declare A=4
# 関数の中で参照
$ function f() {
echo $A;
}
# ちゃんと出力される
$ f
4
declare
コマンドを使って、関数の中で定義した変数を外で使えるようにはできない?
あまりないケースだとは思うが、これもできます。
※続きは次回に。
ディスカッション
コメント一覧
まだ、コメントがありません