FC2ブログ

本を読む

読書やコンピュータなどに関するメモ

Bash 5.0の新機能:localvar_inherit

Qiitaと同時投稿です

Bash 5.0のNEWSファイルをさくっと翻訳したエントリー「bash 5.0のNEWSファイル私訳」を先日書きました。

この中に、localvar_inheritという新しいshoptオプションが追加されたことが書かれています。

o. 新しいshoptオプション:localvar_inherit。設定すると、ローカル変数
   は、直前のスコープにある同じ名前の変数の値を継承します。

自分で訳しておいてなんですが、わかりにくいですね。

Bash 5.0のmanpageでは、こう説明されています。

localvar_inherit
        If set, local variables inherit the value and attributes
        of a variable of the same name that exists at a previous
        scope before any new value  is  assigned.   The  nameref
        attribute is not inherited.

やはりわかりにくいですね。

そこで、ちょこっと調べて試してみた結果を、順を追って説明します。

おさらい①:関数

多くのプログラミング言語と同じく、Bashでも関数を定義できます。定義した関数はコマンドとして実行できます。

$ cat hello.sh
hello() {               # helloという関数を定義
    echo hello
}

hello                   # helloを実行
$ bash ./hello.sh
hello

おさらい②:ローカル変数

単純なシェルでは変数はグローバル変数しかありません。しかしBashでは、localコマンドによって関数内のローカル変数を定義できます。

$ cat localvar.sh
foo() {
  local aaa     # aaaというローカル変数を定義
  aaa=5         # aaaに5を代入
}

aaa=3           # aaaに3を代入
foo             # fooを実行
echo $aaa       # その後でaaaの値は?
$ bash ./localvar.sh
3

おさらい③:ローカル変数はダイナミックスコープ

Bashのローカル変数のスコープは、呼び出し先の関数でも有効です。Common Lispのスペシャル変数や、Emacs Lispのデフォルトのダイナミックスコープ変数、Perlのlocalなどに似ています。

次のように、関数fooと、fooから呼び出す関数barを定義します。すると、fooで定義したローカル変数aaaがbarからも参照できます。

$ cat scope.sh
foo() {
  local aaa=3   # aaaというローカル変数を定義して値を3に
  bar
}

bar() {
  echo $aaa     # barでのaaaの値は?
}

foo
$ bash ./scope.sh
3

同じ変数aaaを参照しているので、barで値を変更すると、fooでも変更されています。

$ cat scope2.sh
foo() {
  local aaa=3   # aaaというローカル変数を定義して値を3に
  bar
  echo $aaa     # barを呼び出した後でaaaの値は?
}

bar() {
  aaa=5         # barでaaaに5を代入
}

foo
$ bash ./scope2.sh
5

ようやく本題:localvar_inherit

では、Bash 5.0の新機能であるlocalvar_inheritを見てみましょう。

localvar_inheritをオンにすると、呼び出し元の変数と同じ名前の変数をlocalで定義したときに、呼び出し元の変数の値と属性が コピー されます。

次の例では、fooとbarで同じ名前の変数aaaを定義しています。barではaaaの値を代入していないのに、fooでaaaに設定した値が参照されます。

$ cat inherit.sh
shopt -s localvar_inherit       # localvar_inheritをオンに

foo() {
  local aaa=3   # fooでローカル変数aaaを定義
  bar
}

bar() {
  local aaa     # barでもaaaを定義。値は代入しない
  echo $aaa     # aaaの値は?
}

foo
$ bash ./inherit.sh
3

ダイナミックスコープと違い、同じ変数を参照するわけではありません。次のように、barでaaaの値を変更しても、fooのaaaの値は変わりません。

$ cat inherit.sh
shopt -s localvar_inherit

foo() {
  local aaa=3
  bar
  echo $aaa     # barを呼び出した後でaaaの値は?
}

bar() {
  local aaa
  aaa=5         # barでaaaに5を代入
}

foo
$ bash ./inherit.sh
3

用途

さて、これをどういうところで使うと便利でしょうか。

普通の変数の値であれば、引数などで渡せば十分です。ただし、配列は引数などでは渡しづらいので、localvar_inheritを使って呼び出し先にコピーするのが便利そうです。

コメント

コメントの投稿

管理者にだけ表示を許可する

トラックバック

http://emasaka.blog65.fc2.com/tb.php/1470-bbd4dff6

 | HOME | 

Categories

Recent Entries

Recent Comments

Recent Trackbacks

Appendix

emasaka

emasaka

フリーター。
連絡先はこのへん

Monthly