Bashプログラミング
 Computer >> コンピューター >  >> プログラミング >> Bashプログラミング

Bash変数チュートリアル – 基本からグローバル変数・ローカル変数まで学べる6つの実用例

Bash変数は、プログラムの実行期間中に必要となる情報を一時的に保存しておくための仕組みです。本記事はBashチュートリアルシリーズの一篇で、他のプログラミング言語と同様にBashでも変数を利用できることを踏まえ、基本的な使い方からグローバル変数とローカル変数の違いまでを、6つの実用的なサンプルを通じて解説します。

Bash変数の基本構文

変数の定義は非常にシンプルで、次の書式に従います。

VARNAME=VALUE

注意: 変数へ代入する際は、「=」記号の前後にスペースを入れてはいけません。「VAR=VALUE」のように書けば、シェルは「=」を代入記号として認識し、この行を変数への代入として処理します。しかし「VAR = VALUE」のようにスペースを挟むと、シェルはVARをコマンド名だと判断し、そのコマンドを実行しようとしてエラーになります。

また、シェルは変数の型を意識しません。変数には文字列でも整数でも実数でも、自由に値を格納できます。

例1: シンプルな変数の代入

次のスクリプトでは、LISTという変数を作成し、「/var/opt/bin」を代入しています。変数の値にアクセスするには、変数名の先頭に「$」を付けるだけでOKです。

$ cat sample.sh
#!/bin/bash
LIST="/var/opt/bin/"
ls -l $LIST

このスクリプトを実行すると、/var/opt/bin の内容が詳細形式で一覧表示されます。

$ ./sample.sh
total 8
drwxrwsr-x 2 bin  bin 4096 Jan 29 06:43 softwares
drwxr-sr-x 5 root bin 4096 Sep  2  2009 llist

補足: 変数名と他の文字列を連結する場合などは、「${LIST}path」のように波括弧で囲むと境界が明確になり、意図しない展開を防げます。

Bash変数のスコープ – ローカル変数とグローバル変数

Bashでは、変数を事前に宣言する必要はありません。ただし、一度も使っていない変数にアクセスしても、警告やエラーは表示されず、単に空の値が返る点に注意してください。

例2: 未代入の変数は空の値になる

$ cat var1.sh
#!/bin/sh
echo "Variable value is: $VAR1"
VAR1="GEEKSTUFF"
echo "Variable value is: $VAR1"

$ ./var1.sh
Variable value is:
Variable value is: GEEKSTUFF

上記のように、変数は初期状態では空の値を持ち、代入を行うことで初めて値を取得できます。ここで登場するexportコマンドは、対話シェルで定義した変数を外部へ引き渡すためのもので、変数のスコープに大きな影響を与えます。

例3: exportしなかった場合の挙動

まず、対話シェル上で変数に値を代入し、それをシェルスクリプト内から参照してみます。

$ VAR2=LINUX

$ cat var2.sh
#!/bin/bash
echo "VAR2=$VAR2"
VAR2=UNIX
echo "VAR2=$VAR2"

スクリプトを実行します。

$ ./var2.sh
VAR2=
VAR2=UNIX

結果は空の値でした。これは、シェルが「VAR2=LINUX」という変数を現在のシェルの中だけで保持しているためです。var2.shの実行時には新しく子シェルが起動してスクリプトが実行されますが、子シェル側にはVAR2の値が引き継がれません。別のプログラム(シェルスクリプトを含む)に変数を引き継がせたい場合は、次のようにexportコマンドで変数をエクスポートする必要があります。

例4: 変数をエクスポートする

$ export VAR2=LINUX

$ cat var2.sh
#!/bin/bash
echo "VAR2=$VAR2"
VAR2=UNIX
echo "VAR2=$VAR2"

再度スクリプトを実行します。

$ ./var2.sh
VAR2=LINUX
VAR2=UNIX
$
$ echo $VAR2
LINUX

今度は、スクリプト実行時にVAR2の値LINUXが正しく引き継がれていることが確認できました。ただし、スクリプト内で変更した値(UNIX)は親シェルには反映されていません。これは、現在のシェル上で直接スクリプトを実行しない限り、変数の変更が対話シェルへ逆流しないためです。

declare文による変数の宣言

Bashのdeclare文を使うと、変数に代入できる値を制限したり、変数の属性(性質)を指定したりできます。declareに続くオプションによって、変数の型を決定します。

構文:

declare option variablename
  • declare: キーワード
  • option: 主なオプションは以下の通り
    • -r : 読み取り専用(read only)変数
    • -i : 整数(integer)変数
    • -a : 配列(array)変数
    • -f : 関数(functions)
    • -x : 宣言と同時に環境変数として後続のコマンドへエクスポート

例5: declareを使った変数宣言

$ cat declar.sh
#!/bin/bash
declare -i intvar
intvar=123 # 整数値を代入
echo $intvar
intvar=12.3 # 整数変数に不正な値を格納しようとした場合
echo $intvar

declare -r rovar=281
rovar=212 # 読み取り専用変数を変更しようとした場合

実行結果を見ると、無効なデータを代入した箇所でエラーメッセージが出力されているのが分かります。

$ ./declar.sh
123
t.sh: line 6: 12.3: syntax error: invalid arithmetic operator (error token is ".3")
123
t.sh: line 11: rovar: readonly variable

-iを付けた整数変数に小数を代入すると構文エラーとなり、-rを付けた読み取り専用変数への再代入は拒否されます。このようにdeclareを使えば、変数の誤用を事前に防ぐことができます。

グローバル変数(環境変数)

グローバル変数は「環境変数」とも呼ばれ、すべてのシェルから利用可能な変数です。printenvコマンドを実行すると、現在設定されているすべての環境変数を一覧表示できます。

$ printenv
SHELL=/bin/bash
HISTSIZE=1000
SSH_TTY=/dev/pts/1
HOME=/root
LOGNAME=root
CVS_RSH=ssh

特定の環境変数だけを確認したい場合は、「printenv HOME」のように変数名を引数に指定するか、「echo $HOME」としても同じ結果が得られます。

ローカル変数

ローカル変数は、コードブロック内でのみ参照できる変数です。localキーワードを使って宣言します。関数内で宣言されたローカル変数は、その関数ブロック内でのみ有効となります。

例6: グローバル変数とローカル変数の比較

$ cat localvar.sh
#!/bin/bash
pprint()
{
  local lvar="Local content"
  echo -e "Local variable value with in the function"
  echo $lvar
  gvar="Global content changed"
  echo -e "Global variable value with in the function"
  echo $gvar
}

gvar="Global content"
echo -e "Global variable value before calling function"
echo $gvar
echo -e "Local variable value before calling function"
echo $lvar
pprint
echo -e "Global variable value after calling function"
echo $gvar
echo -e "Local variable value after calling function"
echo $lvar

スクリプトを実行します。

$ sh t.sh
Global variable value before calling function
Global content
Local variable value before calling function

Local variable value with in the function
Local content
Global variable value with in the function
Global content changed
Global variable value after calling function
Global content changed
Local variable value after calling function

上記の出力から、ローカル変数lvarは関数を呼び出す前後では空の値になっていることが分かります。ローカル変数のスコープは関数内部に限定され、関数の外に出ると消えてしまうのです。一方、グローバル変数gvarは関数の実行後も「Global content changed」という更新後の値を保持し続けています。

まとめ

  • 変数の代入は「VARNAME=VALUE」。イコールの前後にスペースを入れないこと
  • 未宣言の変数を参照してもエラーにはならず、空の値が返る
  • 子プロセスに変数を引き継ぎたい場合はexportを使う
  • declareで変数を読み取り専用や整数型に制限できる
  • 環境変数は全シェルで共有され、printenvで確認できる
  • localで宣言した変数は関数内でのみ有効
  1. Bashシェル関数入門:実用的な6つのサンプル例で学ぶチュートリアル

    Bashシェル関数とは、複数のUNIX/Linuxコマンドをひとつの名前でグループ化し、後からまとめて実行できるようにする仕組みです。Bashシェル関数は通常のUnixコマンドと同じように呼び出すことができ、現在のシェルコンテキスト内で実行されるため、解釈用の新しいプロセスを生成する必要がありません。bashのエイリアス(alias)と関数はどちらも、長いコマンドや複雑なコマンドに対するショートカットを定義するのに役立ちます。しかし、エイリアスでは制御フローや引数の扱いなど、関数ならではの高度な処理を行うことはできません。本記事では、その違いも含めて詳しく解説していきます。この記事は、進行中の

  2. 実用的な5つの例で学ぶBashスクリプト入門チュートリアル

    Unix SedやUnix Awkシリーズと同様に、本シリーズではBashスクリプティングに関する記事を複数回にわたって公開します。実用的なサンプルを交えながら、Bashスクリプティングのテクニックを幅広く解説していきます。 シェルとは、ユーザーが入力したコマンドを解釈して実行するプログラムです。コマンドはユーザーが直接入力するか、「シェルスクリプト」と呼ばれるファイルから読み込まれます。 ユーザーからの入力を直接読み取る場合、そのシェルは対話型(インタラクティブ)シェルと呼ばれます。 一方、ファイルからコマンドを読み込んで実行する場合は非対話型(ノンインタラクティブ)シェルと呼ばれます。この