ファイヤープロジェクト
BASHでの変数について
2004-03-14T23:45+09:00   matsu
BASHスクリプトにおける変数の取扱について説明する.
変数は宣言せずに使用できる.以下の文では,変数xに文字列hogeを代入している.
x=hoge
このとき,等号の両側にスペースをいれてはいけない.この変数xの内容を参照するには,変数の前に$を付ける.
echo $x
変数の値は文字列型として扱われる.そして数値の操作をするときに数値文字列を数値に変換する.また,大文字と小文字は区別される.変数の開放にはunsetを使用する.
$ x=100
$ echo $x
100
$ unset x
$ echo $x

パラメータは空白,タブ,改行コードで区切られる.変数にこれらの値を代入するには,その値をダブルクォーテーションで囲う.
x="hoge foo"
$変数名をダブルクォーテーションで囲うと,その変数の値は展開される.したがって,以下の二つの結果は等しい.
echo $x
echo "$x"
逆に$変数名をシングルクォートで囲うとその変数の値は展開されない.したがって,以下の結果は$xである.
echo '$x'
この機能は,シングルクォートで囲った部分をBASHに解釈させたくない場合に使う.例えば,xで始まる全パッケージをインストールしたい場合は以下を実行する.
echo -e '\a'
\$変数名だと,\が$の持つ特別な意味を書き消す.したがって,以下の結果は$xである.
echo \$x
\もBASHに解釈させたくない特殊文字を使用するときに使う.以下の文はechoコマンドに\aを渡している.
echo -e \\a
\\aが\aだった場合はBASHがechoコマンドに渡すパラメータがaとなり,結果としてaと表示される.\\aだとBASHはechoコマンドに\aを渡す.そしてビープ音が鳴る.
環境変数とは,あらかじめ環境で設定してある値で初期化される変数である.たとえば$HOMEはホームディレクトリのパスを値としてもつ.環境変数は普通大文字である.逆にユーザ定義の変数は小文字を使う事が多いらしい.環境変数はコマンドenvで確認できる.
スクリプトを作成するときにパラメータを取得できないと困ることがある.パラメータは以下の変数で表される.
$0
スクリプトの名前
$#
渡されたパラメータの数
$$
スクリプトのプロセスID
$1,$2,...
スクリプトのパラメータ
$*
全パラメータを表す一つの変数.各パラメータは$IFSで区切られる.ダブルクォートしないと,BASHに$0,$1,$2,....と展開される気がする(*は全ての文字列に一致する).
$@
全パラメータを表す一つの変数.各パラメータは$IFSに関係なく(おそらくスペースで)区切られる.
BASHでは,1次元配列も使用できる.以下のように,通常の変数と同様に宣言なしで使用できる.
$ ARR[0]=1
$ echo ${ARR[0]}
1
$ ARR[100]=100
$ echo ${ARR[100]}
100
上のように,配列の要素iへの値の代入は以下に記述する.
配列名[i]=値
iは0以上であり,上の例のようにいきなり第100要素に格納することもできる.配列の要素は以下の形式で参照する.
${配列名[i]}
通常の変数では,ブラケット{}を変数を厳密に指定したい場合に使用したが,配列の場合は常に必須である.ただし,0番目の要素を指定する場合に限り,ブラケットとインデクスを使用しなくてもよい.さらにブラケットを使用してインデクスを指定しない場合も0番目の値を返す.
ARR[0]=50
$ echo $ARR
50
$ echo ${ARR}
50
0番目の要素を初期化していない場合は空が返る.
$ B[3]=3
$ echo $B

$ echo ${B}

$ echo ${B[3]}
3
配列への値の代入には,以下のように複合代入も使用できる.
配列名=(値1 値2 値3 値4 値5....)
値は0番目の要素から順に格納されていく.インデクスに*か@を指定すると,その配列の全要素が返る.
$ C=(1 2 3 4 5)
$ echo ${C[*]}
1 2 3 4 5
さらに配列名の頭に#をつけ,インデクスに*か@を指定すると,配列の要素数が返る.
$ echo ${#C[*]}
5
$ echo ${#C[@]}
5
配列の領域を開放するには,通常の変数と同様にunsetを使用する.
$ echo ${B[@]}
4 3
$ unset B

$ echo ${B[@]}

BASHでは宣言なしに変数を使用することができるが,変数を明示的に宣言することもできる.この際に,変数に対していくつかの属性を付加することができる.変数の宣言にはdeclareあるいはtypesetを使用する.
declare [-afFirx] [-p] [name[=value]]
typeset [-afFirx] [-p] [name[=value]]
nameが変数名で,valueが変数の初期化値である.nameを指定しなければ,現在の全変数の値を表示する.各オプションについて以下に示す.
a
変数を配列変数として宣言する.
f
変数を関数として扱う.
F
関数定義の表示を抑制し,関数名と属性のみを表示する.-Fを指定すると-fも指定したことになる.
i
変数を整数として扱う.変数に値が代入されたときに,算術式を評価するようになる.
r
変数を読み込み専用変数として扱う.読み込み専用変数には値を代入したりunsetできなくなる(※).
x
変数をエクスポートする.
p
変数の属性と値を表示する.
以下はtypesetで配列変数を扱う例である.
$ typeset -a ARR
$ typeset -p ARR
declare -a ARR='()'
$ ARR=(1 2 3 4 5)
$ typeset -p ARR
declare -a ARR='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5")'
$ unset ARR
$ typeset -p ARR
bash: typeset: ARR: not found
次にdeclareで関数を格納する変数を扱う例を示す.
$ declare -f func
$ function func1 () { echo 'This is func1'; }
$ function func2 () { echo 'This is func2'; }
$ func=func1
$ $func
This is func1
$ func=func2
$ $func
This is func2
ただし,これは特にdeclareしてなくてもできる.最後にtypesetで読み込み専用変数を扱ってみる.
$ typeset -r RO
$ RO=1
bash: RO: readonly variable
$ unset RO
bash: unset: RO: cannot unset: readonly variable
$ typeset +r RO
bash: typeset: RO: readonly variable
$ typeset -r RO=1
bash: typeset: RO: readonly variable
上記のように,読み込み専用変数は読み込み専用属性を取り除くことも上書き的に宣言し直すこともできないので,値を持たせたいときには,typesetやdeclare時に忘れずに値を指定する.
$ typeset -r RO2=1
$ echo $RO2
1
※ readonlyというコマンドも同様の機能を提供する.
局所変数を使用することもできる.BASHでは特に指定しない限り変数は全て大域変数である.変数を局所変数として指定するには,以下の方法がある.
  • 関数内でdeclareやtypesetコマンドを使用して,変数を宣言する.
  • 関数内でlocalコマンドを使用して変数を宣言する.
いづれもスコープは局所変数を宣言した関数とその子の関数である.localコマンドはdeclare,typesetを局所変数に限定したようなもので,両者と同じ引数をとるが,関数内以外で使用するとエラーとなる.
$ local LOCAL
bash: local: can only be used in a function
局所変数と大域変数の違いを確認してみた.
$ typeset -i GRB=0
$ function localTest() {
    local -i LOCAL;
    let LOCAL++;
    let GRB++;
    echo "LOCAL=$LOCAL";
    echo "GRB=$GRB";
} 
$ localTest
LOCAL=1
GRB=1
$ localTest
LOCAL=1
GRB=2
matsu(C)
Since 2002
Mail to matsu