本文へスキップ
BecomeCoder

シェルスクリプトコース · 第6章 関数と構造化 · レッスン27

local ― 関数の中だけの変数

ブラウザで完結

導入

シェルの変数は、何も指定しないとスクリプト全体で共有されます。関数の中で i を使ったら、外側のループi を壊してしまった——これは実際に起きるバグです。local で防ぎましょう。

説明

local 変数名 と書くと、その変数は関数の中だけのものになります。関数を抜けると、元の値に戻ります。

#!/bin/bash

message="外側のメッセージ"

bad_function() {
  message="関数が書き換えた"
}

good_function() {
  local message="関数の中だけ"
  echo "関数の中: $message"
}

echo "最初: $message"
bad_function
echo "bad のあと: $message"

message="外側のメッセージ"
good_function
echo "good のあと: $message"

実行すると、bad_function は外側の値を壊し、good_function は壊さないことが分かります。

flowchart TD
    A["message=外側"] --> B{"関数の中で代入"}
    B -->|"local なし"| C["外側の message が変わる(事故)"]
    B -->|"local あり"| D["関数の中だけ変わる(安全)"]
    D --> E["関数を抜けると外側は無傷"]

ルールはシンプルです。関数の中で新しく作る変数は、すべて local を付ける。付けて困ることはありません。特にループ変数(ifileline)は事故が起きやすいので要注意です。

引数も同じ考え方で扱います。$1 をそのまま何度も使うより、冒頭で名前のある変数に受け直すと読みやすくなります。

process_file() {
  local file="$1"
  local mode="${2:-normal}"   # 2つ目は省略可、既定は normal
  echo "$file$mode モードで処理"
}

やってみよう

スクリプトを実行して、bad のあと では値が書き換わり、good のあと では元のままであることを見比べましょう。次に good_functionlocal を消して実行すると、bad_function と同じ結果になります。local の有無だけで挙動が変わることを、自分の目で確かめてください。

演習

good_function を呼んだあとも外側の message外側のメッセージ のままであることを表示してください(good のあと: 外側のメッセージ が出ればOK)。

ヒント1を見る

変更は不要です。まずそのまま実行して結果を確かめてください。

ヒント2を見る

local を消すと結果が変わります。付け直すと元に戻ります。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

シェルスクリプト(シミュレート)

スクリプトを書くエディタと、それを動かす仮想シェルを読み込みます(本物のbashではなく、動きを再現した学習用の環境です)。
スクロールして表示された時点でも自動で読み込まれます。