Bashのビルトインコマンド `declare` の使い方紹介(変数のlocalスコープ)

2019-02-05Bash, CentOS, Cygwin, Linux, Ubuntu

またまた、以下のエントリの続き。

  1. シェルスクリプトサンプルコードでよく見かけるtypesetやdeclareってなに? | ゲンゾウ用ポストイット
  2. Bashのビルトインコマンド “declare” の使い方紹介(その1) | ゲンゾウ用ポストイット
  3. Bashのビルトインコマンド “declare” の使い方紹介(その2) | ゲンゾウ用ポストイット
  4. Bashのビルトインコマンド “declare” の使い方紹介(その3) | ゲンゾウ用ポストイット

※だんだんシリーズみたいになってきた(笑)

今回は 前回 の続きで、Bashにおける変数のスコープ(参照可能な範囲)について。

検証環境

$ bash -version
GNU bash, バージョン 5.0.2(1)-release (x86_64-apple-darwin18.2.0)
Copyright (C) 2019 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>

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 -rreadonly の関係と同じように、 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 コマンドを使って、関数の中で宣言した変数を外で使えるようにはできない?

あまりないケースだとは思うが、これもできる。

※続きは次回

2019-02-05Bash, CentOS, Cygwin, Linux, Ubuntu