シェルとシェルスクリプト 3 変数〜soureコマンド

変数

 プログラムをする上で、非常に重要な考え方が変数である。簡単に言うと 「 箱 」 で、中に数値や文字列が入る。シェルスクリプトプログラミングでは、変数に数値や文字列を代入し、それを利用することができる。変数の代入は 「 = 」 を使って行い、参照は 「 $ 」 を付けて行われる。

実行例 シェル変数の作成

$ abc=123
( 変数 abc を定義 ( 内容は123 ) )

$ echo $abc
123
( 変数 abc の内容を表示する )

 変数 abc に 123 を代入した。bash では、一次元の配列変数を使用することができる。要素は角括弧 [] で囲う。配列変数の内容を表示する場合は、$ の後ろに波括弧 {} で配列変数を囲う。

$ abc[0]=123
$ abc[1]=456
$ echo ${abc[0]}
123
( abc[0] の内容を表示する )

$ index=1
$ echo ${abc[$index]}
( abc[1] の内容を変数を使って表示する )

シェル変数と環境変数

 シェルには2種類の変数がある。シェル変数と環境変数である。

 シェル変数は、実行しているシェルの内部でのみ有効である。

 環境変数は、そこから実行されたコマンド内でも有効になる。環境変数はシェル変数から作成できる。

実行例 環境変数の作成

export コマンドを使って、環境変数を作成する。

$ export abc
( シェル変数 abc を環境変数 abc にする )

$ export xyz=234
( 環境変数 xyz を作成し、 234 を代入する )

 1つ目のコマンドでは環境変数を作成しているが、値は代入されていない。一方で2つ目のコマンドでは、234 という値が代入されている。

 次に、2つのスクリプトBBb.sh と CCC.sh を使い、シェル変数と環境変数の動作の違いについて確認してみる。

$  vi BBB.sh
( インサートモードで以下を入力 )
#!/bin/bash
xxx=123
export yyy=234
echo xxx=$xxx in BBB.sh
echo yyy=$yyy in BBB.sh
./CCC.sh

シェル変数 xxx に 123 を代入している。

環境変数 yyy に234 を代入している。

$ vi CCC.sh
( インサートモードで以下を入力 )
#!/bin/bash
echo xxx=$xxx in CCC.sh
echo yyy=$yyy in CCC.sh

シェルスクリプトを実行する。

$ ./BBB.sh
xxx=123 in BBB.sh
yyy=234 in BBB.sh
xxx= in CCC.sh
yyy=234 in CCC.sh

このスクリプトを実行した時、シェルスクリプト CCC.sh の中で xxx の値は表示されない。なぜならシェル変数は引き継がれないからである。一方で yyy は環境変数なので CCC.sh まで引き継がれ、値が表示される。

read コマンド

read コマンドは標準出力からデータを読み込む。既に変数にデータが入っていた場合、新しいデータに上書きされる。

$ read 変数名

実行例

$ echo $abc
123
( 変数 abc の値が表示される )

$ read abc
456
( 値を入力する )

$ echo $abc
456
( 変数 abc の値が書き換わっている )

シェル変数

 シェル変数の一覧を表示する場合は、set コマンドを利用する。また、削除する場合は unset を利用する。

実行例 シェル変数一覧表示と削除

$ set
( シェル変数が表示される ( 数が多いので省略 ) )

$ set | grep abc
( abcで始まるシェル変数のみ表示する )

abc=456

$ unset abc
( シェル変数 abc を削除する )

$ set | grep abc
( abcで始まるシェル変数のみ表示する )

$ ( シェル変数 abc は削除されたので、表示されない )

環境変数

 現在の環境変数の一覧を表示するには、env コマンドを利用する。また登録済みの環境変数を削除する場合は unset コマンドを利用する。

実行例

$ env
( 環境変数が表示される ( 数が多いので省略 ) )

$ env | grep xyz
xyz=234
( xyz を含む環境変数を表示する )

$ unset xyz
( 環境変数 xyz を削除する )

$  env | grep xyz
( xyz を含む環境変数を表示する )

$ ( 環境変数 xyz は削除されたので、表示されない )

引用符

 シェルスクリプトにおいて、文字列を引用符で囲むことができる。利用できる引用符には' ( シングルクォート ), " ( ダブルクォート )、 ` ( バッククォート ) があり、使用される引用符により囲まれた文字列の処理が異なる。

 シングルクォートで囲まれた文字列の中に、参照用の 「 $ 」 付きの変数がある場合、 「 $ 」 も文字列として認識されるため、変数は展開されない。

 ダブルクォートの場合、引用符内の 「 $ 」 付き変数は展開された文字列になる。

 バッククォートで囲まれた文字列はコマンドとして解釈され、この時 「 $ 」 付き変数があれば、それを展開した上でコマンドが実行される。引用符は入れ子が可能である。

実行例 引用符の動作確認

シングルクォートで囲むと $ が文字列として認識される

$ ABC = 123
(変数を定義)

$  echo 'Value of ABC is $ABC.'
Value of ABC is $ABC.
( $ABC が文字列として認識され、表示された )

ダブルクォートで囲むと $ は変数として認識される。

$ echo "Value of ABC is $ABC."
Value of ABC is 123.
( $ABC が変数として認識され、内容である123が表示された )

バッククォートで囲むとコマンドとして認識される

$ XYZ=`date`;
( バッククォート )

$ echo "It is $XYZ now."
It is 2021年 2月 2日 火曜日 14時19分06秒 JST now.
( $XYZ に dateコマンドの実行結果が表示される )

$ echo "It is `date`now."
It is 2021年 2月 2日 火曜日 14時22分56秒 JSTnow.
( ダブルクォートで全体の文字を囲み、バッククォートで囲んだ date コマンドを挿入して、変数 XYZ の代入を省略 )

引数

 シェルスクリプトでは、実行時にオプションを引数として参照することができる。引数は $1、 $2、...と $ の後に引数の番号を指定することで参照できる。

実行例 args.sh を作成して、引数呼び出しの動作を確認する。
$ vi args.sh
( インサートモードで以下を入力 )
#!/bin/bash

echo '$1:' $1;
echo '$2:' $2;
echo '$3:' $3;
echo '$0:' $0;
echo '$#:' $#;
$ ./args.sh aaa bbb ccc
$1: aaa
$2: bbb
$3: ccc
$0: ./args.sh
$#: 3
( $1~$3 は引数、$0 はコマンド名、$# は引数の数を示す )

shift コマンドの確認

 shift コマンドは引数の順序をずらす。shift を実行すると、$2 が $1 に、 $3 が $2 になる。

実行例 shift コマンドの確認

$ vi argsshift.sh
( インサートモードで以下を入力 )
#!/bin/bash
  
echo '$1:' $1;
echo '$2:' $2;
echo '$3:' $3;
shift
echo '$1:' $1;
echo '$2:' $2;
$ ./argsshift.sh aaa bbb ccc
$1: aaa
$2: bbb
$3: ccc
$1: bbb ( $1 が bbb に変わった )
$2: ccc ( $2 が ccc に変わった )

エスケープシーケンス

 プログラミング言語には、特別な扱いを受ける文字がある。例えば、 echo コマンドで 「 Value od ABC is "123". 」 のように "" ( ダブルクォート ) を出力する方法を考えてみる。

$ ABC = 123
$ "Value of ABC is "$ABC"."
Value of ABC is 123.
( $ABC を "" で囲っても "" が表示されない )

$ echo "Value of ABC is \"$ABC\"."
Value of ABC is "123".
( 表示したい "" の直前に \ をつけることで "" を表示できる )
$ echo 'Value of ABC is "$ABC". '
Value of ABC is "$ABC".
( 文字列全体を '' で囲むことでも "" を表示できる )

$ echo "Value of ABC is \$ABC."
Value of ABC is $ABC.
( ダブルクォートで囲んだ文字列内で $ を表示したい場合も直前で \ を記述することで可能になる )

 このようにシェルスクリプトでは、\ ( バックスラッシュ ) はエスケープ文字と呼ばれ、特別な文字で直後の一文字の扱いを変更する。使用する引用符との組み合わせで、文字の扱いを変えたい場合にも有効である。

 \ は改行コードにも有効である。 \ を行末に付与することで、文字列の途中で折り返すことができる。適切に改行を入れることでコマンドの視認性を向上できる。   実行例

$ echo "I am a cat. As yet I have no name."
I am a cat. As yet I have no name.

$ echo "I am a cat.\
> As yet I have no name."
I am a cat.As yet I have no name.
( 途中でバックスラッシュを入れても改行は無視され同じ結果となる )

バックスラッシュにより改行は、シェルスクリプト内でも使うことができる。バックスラッシュは本来 \ であるが、多くの日本語環境では ¥ と表示される。

実行例

$ vi escape.sh
( インサートモードで以下を入力 )
#!/bin/bash
  
echo "I am a cat.\
As yet I have no name."
$ ./escape.sh
I am a cat.As yet I have no name.

 バックスラッシュには他にも用途があり、次に続く1文字とセットで特別な意味を持つ文字俺つとする、エスケープシーケンスという手法がある。

 よく使用されるものとして \t ( タブ )、 \n ( 改行 )、 \ 000 ( 数字で8進数表記の文字 ) がある。

実行例 echo コマンドでエスケープした文字を解釈するオプション -e で試してみる。

$ echo -e "I am a cat. \nAs yet I have no name\041"
I am a cat. 
As yet I have no name!
( \n は改行に変わり、 \041 は ! に変わった )

source コマンド

 source コマンドは bash などのシェルの内部コマンドで、指定されたファイルを読み込んでシェル環境を設定する。ファイル内容はシェルコマンドと解釈して実行する。

 一般的な用途としては、シェルの環境設定ファイルである ".bash_profile" などを設定変更後、ログインし直さずに設定を現在のシェル上で有効にする場合に使われる。

実行例 setsh というシェルスクリプトを作成し、$abc という変数に xyz を定義して、 source コマンドで読み込んでみる。

$ vi set.sh
( インサートモードで以下を入力 )

"!/bin/bash
abc=xyz
echo $abc
$ echo $abc

( $abc には何も格納されていないので、何も表示されない )
$ ./set.sh
xyz
( スクリプト内で設定された変数 abc の値が echo で出力された )

source コマンドでset.sh を読み込む。

$ source set.sh
xyz
(スクリプト内で設定された変数 abc の値が echo で出力された )

source コマンドで読み込んだことにより、set.sh の終了後も変数 abc に値が格納されたままになる。

$ echo $abc
xyz