Shellスクリプト基礎知識(全11記事+1)
├─シェルスクリプトの基本事項!
├─変数と特殊変数について!
├─演算子「算術演算子」「比較演算子」について!
├─条件分岐「if」「case」について!
├─ループ処理「for」「while」について!
├─文字列置換「bash」「sed」について!
├─複数行のテキスト出力!ヒアドキュメントについて!
├─書式?戻り値?シェルスクリプト内の関数について!
├─シェルの組み込みコマンドについて!
├─クォートとは?コマンド置換とは?実現方法と内容の違いについて!
└─リダイレクトとは?標準入力・出力、標準エラー出力等について!
(補足)シェルスクリプトの設計書とは?必要な項目や書き方等を解説!
シェルスクリプト上ではシェル変数によって変数を扱うことが可能です。また、シェル変数以外に、特殊変数と呼ばれる一種の変数が存在します。
極稀に変数の中にコマンドを代入して実行させたい、つまり「2重展開」を行いたいと検索してこのページへたどり着く方がいるようです。2重展開については「eval」コマンドを参照してください。
シェルの変数とは?
シェルには「シェル変数」と「特殊変数」が機能として予め用意されています。シェル変数は環境変数としてエクスポートすることが可能です。
シェル変数とは?
シェルスクリプトにおける「変数」は、データを一時的に保存し、それを必要なときに呼び出して利用するための「名前付きの箱」のようなものです。プログラムの処理を効率化し、コードをより簡潔にするために不可欠な要素です。
シェルでは、シュル変数によって値を一時的に保管しておくことが可能です。後で必要な時にシェル変数から値を取り出します。簡単に言うと、パソコンで処理をするときに、データを代入して効率的に処理をする箱といった認識で良いでしょう。
例えば、ユーザがOSにログインした時、起点となるディレクトリをホームディレクトリといいますが、これは$HOMEというシェル変数の値としてセットされています。
スクリプト内で繰り返し使う値や、動的に変化する情報を変数に格納することで、手間を省き、管理しやすくなります。
変数の使い方
シェルスクリプトで変数を使う方法は非常にシンプルです。以下のように、変数に値を割り当て、必要に応じて参照します。
変数の定義 (後述)
変数名=値
変数の参照 (後述)
$変数名
使用例: 変数を使った簡単なスクリプト
!/bin/bash
# 変数の定義
name="Taro"
age=25
# 変数を参照して表示
echo "こんにちは、私の名前は $name です。"
echo "年齢は $age 歳です。"
このスクリプトでは、name と age にそれぞれ値を代入し、それを echo コマンドで出力しています。このように変数を使うことで、スクリプトを柔軟に動作させることができます。
変数を使うメリット
- 可読性が向上: スクリプトの内容が明確になり、保守性が高まる。
- 再利用性: 一度設定した値を複数回使用できるため、同じ値を繰り返し書く必要がない。
- 動的な値の管理: 実行時に値を変更する必要がある場合でも、変数を使えば簡単に対応可能。
変数名についてのルール
シェル変数の名前には、アルファベット、数字、アンダースコア(_)を使うことができます。適当な文字、数値、記号を自由に組み合わせて、スクリプト内で「変数にすると宣言」すればよいのです。
ただし、先頭に数字を設定することは出来ません。また、アルファベットの大文字と子文字は別物として取り扱われますので注意してください。
シェル変数宣言の書式
変数=値
ココに注意
シェルスクリプトでは、変数への代入で「=」の後にスペースを入れることは出来ません! また、代入する値は、スペースや特殊記号などがシェルによって解釈されるのを防ぐため、基本的にシングル or ダブルクォート('')で囲むようにします。
変数の基本操作:定義、参照、削除の方法
シェルスクリプトでは、変数を使うことでデータを一時的に保存し、効率的にスクリプトを管理することができます。このセクションでは、変数の「定義」「参照」「削除」の基本操作を解説します。これらの操作を理解することで、スクリプトを柔軟に作成できるようになります。
シェル変数の定義方法
実際にコンソールへ、変数の宣言をしてみます。
site_name="Beエンジニア"
上記の代入の書式により、任意のシェル変数(変数名)に値を代入することができます。値を省略すると値が空文字列になりますが、シェル変数自体は定義されます。
実際にシェルスクリプトで記述するとこんな感じになります。
1 2 3 | [root@CentOS7 ~]# site_name="Beエンジニア" [root@CentOS7 ~]# echo ${site_name} Beエンジニア |
「echo」コマンドは、メッセージなどを表示するコマンドです。「echo "メッセージ"」でメッセージを表示します。「echo "${変数名}"」で環境変数やシェル変数を表示する際にも使用します。
変数名には「変数を使う目的」を名前にしましょう。そうすれば読みやすいスクリプトになります。
シェル変数の参照は、変数名の頭に$を付けることによって行います。ただし、この際に値に含まれるスペースや*などのパス名展開の文字が解釈されてしまうのを防ぐため、基本的に全体をダブルクォート("")で囲みます。
シェル変数の参照
echo "${site_name}"(※1)
echo "$site_name"(※2)
※1:{}は、変数名の直後に別の文字列が続く場合、変数と文字列の区切りとして使用しています。
※2:{}を省略することも可能です。ただしスクリプト可読性が下がります。
シェル変数の初期設定(=、-、?、+)
前章でもお伝えした通り、シェル変数は、変数名と代入する値を「=(イコール)」で結ぶことでシェル変数をセットします。
ですが、もっと柔軟に値を設定する方法もあります。
その変数が既に利用されているか、または、その変数は未設定(値がヌル)か、もしくは、まだ一度も使用されていない変数か、という条件によって代入する値や表示する内容を変えたりすることもできるのです。
コマンドの書式
${変数:=値}(※1)
${変数:-値}(※2)
${変数:?メッセージ}(※3)
${変数:+値}(※4)
※1:変数がこれまで未使用、未設定の状態の時、値を代入して指定した値をそのまま返す。
※2:変数がこれまで未使用、未設定の状態の時、値を代入しないまま指定した値をそのまま返す。
※3:変数がこれまで未使用、未設定のときにメッセージの部分が表示されます。
※4:変数に何らかの値が設定されているときに、値を取り替えて表示します。
表示される変数の値は、その時点で対象の変数を既に利用しているかどうかで違ってきます。
ココに注意
いずれも「:(コロン)」は省略可能です。「:」があれば、この変数がこれまで未使用(はじめて登場した場合)かヌル値がセットされているときに、後半(:以後)の処理を行います。「:」がなければ変数がこれまで未使用の場合に限って処理します。
「=」によるシェル変数の設定
変数がこれまで未使用、未設定の状態の時、値を代入して指定した値をそのまま返します。
# 変数${var}へ「」を代入した場合(未使用の状態)
var=
echo ${var:=bbb}
# 変数${var}へ「aaa」を代入した場合
var=aaa
echo ${var:=bbb}
実行結果は下記の通り
1 2 3 4 5 6 7 8 9 10 11 | [root@CentOS7 bin]# var= [root@CentOS7 bin]# echo ${var:=bbb} bbb 👈 変数が未設定の場合、値を代入して指定した値を返す。 [root@CentOS7 bin]# echo ${var} bbb 👈 値が代入されている。 ------------------------------------------------------------------ [root@CentOS7 bin]# var=aaa [root@CentOS7 bin]# echo ${var:=bbb} aaa 👈 変数に値が設定されている為、設定された値を返している。 [root@CentOS7 bin]# echo ${var} aaa |
「-」によるシェル変数の設定
変数がこれまで未使用、未設定の状態の時、値を代入しないまま指定した値をそのまま返します。
# 変数${var}へ「」を代入した場合(未使用の状態)
var=
echo ${var:-bbb}
# 変数${var}へ「aaa」を代入した場合
var=aaa
echo ${var:-bbb}
実行結果は下記の通り
1 2 3 4 5 6 7 8 9 10 11 | [root@CentOS7 bin]# var= [root@CentOS7 bin]# echo ${var:-bbb} bbb 👈 変数が未設定の場合、値を代入せず指定した値を返す。 [root@CentOS7 bin]# echo ${var} 👈 値は代入されていない。 ------------------------------------------------------------------ [root@CentOS7 bin]# var=aaa [root@CentOS7 bin]# echo ${var:-bbb} aaa 👈 変数に値が設定されている為、設定された値を返している。 [root@CentOS7 bin]# echo ${var} aaa |
「?」によるシェル変数の設定
変数がこれまで未使用、未設定のときにメッセージの部分が表示されます。
# 変数${var}へ「」を代入した場合(未使用の状態)
var=
echo ${var:?"var is not set"}
# 変数${var}へ「aaa」を代入した場合
var=aaa
echo ${var:?"var is not set"}
実行結果は下記の通り
1 2 3 4 5 6 7 8 9 10 11 | [root@CentOS7 bin]# var= [root@CentOS7 bin]# echo ${var:?"var is not set"} -bash: var: var is not set 👈 値が未設定の場合のみ、メッセージを表示する。 [root@CentOS7 bin]# echo ${var} 👈 値は代入されていない。 ------------------------------------------------------------------ [root@CentOS7 bin]# var=aaa [root@CentOS7 bin]# echo ${var:?"var is not set"} aaa [root@CentOS7 bin]# echo ${var} aaa |
「+」によるシェル変数の設定
変数に何らかの値が設定されているときに、値を取り替えて表示します。
# 変数${var}へ「」を代入した場合(未使用の状態)
var=
echo ${var:+bbb}
# 変数${var}へ「aaa」を代入した場合
var=aaa
echo ${var:+bbb}
実行結果は下記の通り
1 2 3 4 5 6 7 8 9 10 11 | [root@CentOS7 bin]# var= [root@CentOS7 bin]# echo ${var:+bbb} 👈 値は代入されていない。 [root@CentOS7 bin]# echo ${var} 👈 値は代入されていない。 ------------------------------------------------------------------ [root@CentOS7 bin]# var=aaa [root@CentOS7 bin]# echo ${var:+bbb} bbb 👈 値が設定済みの場合のみ、値を取り換えて表示する。 [root@CentOS7 bin]# echo ${var} aaa 👈 元の値に変更はない。 |
シェル変数の参照
定義した変数の値を参照する際は、変数名の前に $ を付けます。
コマンドの書式
$変数名
name="Taro"
age=25
echo "名前: $name"
echo "年齢: $age"
上記を実行すると、以下のように出力されます。
1 2 3 4 | [root@CentOS7 -]# echo "名前: $name" # 出力: 名前: $name 名前: Taro [root@CentOS7 -]# echo "年齢: $age" # 出力: 年齢: $age 年齢: 25 |
- ダブダブルクォート内で変数を使用すると、その値が展開されます。
- シングルクォート内では変数は展開されません。
シェル変数の削除
不要になった変数を削除する場合は、unset コマンドを使用します。
コマンドの書式
unset 変数名
unset name
echo $name # 出力: 空
この例では、変数 name が削除されたため、echo $name は空の出力となります。
変数操作の注意点
ローカル変数と環境変数:
export を使うことで、変数を環境変数として他のプロセスに引き継ぐことができます。
export name="Taro"
特殊文字:
変数にスペースや特殊文字を含めたい場合は、値をダブルクォートで囲む必要があります。
greeting="Hello, World!"
実践例:
変数の操作を組み合わせたスクリプト:[variable_operations_example.sh]
#!/bin/bash
# 変数の定義
user="Alice"
greeting="Hello"
# 変数の参照
echo "$greeting, $user!"
# 変数の削除
unset user
echo "User: $user" # 出力は空
実行例
1 2 3 | [root@CentOS7 -]# sh variable_operations_example.sh Hello, Alice! User: |
変数の種類:ローカル変数と環境変数の違い
シェルスクリプトで扱う変数には、「ローカル変数」と「環境変数」という2つの種類があります。それぞれの特性を理解し、適切に使い分けることで、スクリプトの効率性と可読性が向上します。このセクションでは、それぞれの違いと使い方を解説します。
ローカル変数とは?
ローカル変数は、定義されたシェルやスクリプト内でのみ有効な変数です。スコープ(有効範囲)が限定されているため、他のスクリプトやプロセスには影響を与えません。
ローカル変数の特徴
- スクリプト内でのみ使用可能。
- 同じ名前の変数が別のスクリプトで使われても干渉しない。
- 一時的な値や計算結果を保持するのに適している。
#!/bin/bash
name="Taro" # ローカル変数
echo "ローカル変数 name: $name"
環境変数とは?
環境変数は、現在のシェルだけでなく、そのシェルから起動されたすべてのプロセスやスクリプトでも利用可能な変数です。システム全体やアプリケーション設定を管理するためによく使用されます。
環境変数の特性
- シェル間やスクリプト間で値を共有可能。
- export コマンドを使って設定。
- システムやユーザーに関する情報を格納するのに適している。
#!/bin/bash
export PATH="/usr/local/bin:$PATH" # 環境変数
echo "環境変数 PATH: $PATH"
ローカル変数と環境変数の違い
シェルスクリプトで変数を扱う際には、その用途やスコープに応じて「ローカル変数」と「環境変数」を使い分ける必要があります。ローカル変数はスクリプト内で完結する一時的なデータ保存に適しており、環境変数はシステムや他のプロセスと情報を共有するために利用されます。
項目 | ローカル変数 | 環境変数 |
---|---|---|
スコープ | 定義されたシェル/スクリプト内のみ | シェルやプロセス全体で有効 |
宣言方法 | 変数名=値 | export 変数名=値 |
用途 | 一時的なデータ保存 | システム設定や共有情報の管理 |
デフォルト変数 | 該当なし | PATH, HOME, USER など |
スクリプト例 [check_vars_test.sh]
# !/bin/bash
# ローカル変数
local_var="私はローカル変数です"
export global_var="私は環境変数です"
# 別のスクリプトを呼び出し
./check_vars.sh
check_var.sh
#!/bin/bash
echo "ローカル変数: $local_var" # 空になります
echo "環境変数: $global_var" # 値が表示されます
実行結果
1 2 3 | [root@CentOS7 -]# sh test.sh ローカル変数: 環境変数: 私は環境変数です |
- ローカル変数は呼び出したスクリプト内では無効です。
- 環境変数は他のスクリプトやプロセスでも参照可能です。
変数のスコープとは?
シェルスクリプトでは、変数のスコープ(有効範囲)を正しく理解し、必要に応じて環境変数として持続性を持たせることが重要です。export コマンドを活用することで、変数を環境変数に昇格させ、スコープを広げることができます。
スコープとは、変数がどの範囲で有効かを決めるルールです。シェルスクリプトでは、以下の2種類のスコープがあります
変数のスコープ
- ローカルスコープ(スクリプト内のみ有効)
- 変数はそのスクリプト内または現在のシェルセッションでのみ有効。
- デフォルトでこのスコープが適用されます。
- グローバルスコープ(環境変数として有効)
- export コマンドを使用すると、変数を環境変数として他のプロセスやスクリプトで利用可能にできます。
環境変数の設定において、exportコマンドは非常に便利で多用途です。
実用例 1: PATH の設定
exportを使用することで、コマンドの検索パスに新しいディレクトリを簡単に追加できます。この設定により、カスタムスクリプトやプログラムをシステム全体で手軽に利用できるようになります。
以下のコマンドを実行することで、/usr/local/mybinディレクトリを現在のPATHに追加し、その変更を反映した状態を確認できます。
export PATH="/usr/local/mybin:$PATH"
echo $PATH
実用例 2: アプリケーション設定の共有
環境変数を利用して、データベース接続情報やAPIキーなどのアプリケーション設定を共有できます。これにより、設定をスクリプトやプログラムに簡単に渡すことができ、効率的な運用が可能になります。
たとえば、以下のコマンドを実行して、データベース接続情報を環境変数DB_URLとして設定し、それをスクリプト内で活用します。
export DB_URL="mysql://user:password@localhost:3306/mydb"
./connect_to_db.sh
これらの実例を活用することで、システムやアプリケーションの設定を効率的に管理できるようになります。
環境変数の利用はシンプルながら非常に強力なツールであり、特にチームやプロジェクトでの運用時に効果を発揮します。
ローカル変数と環境変数の使い分け
シェルスクリプトを効率的に作成するには、ローカル変数と環境変数の違いを理解し、適切に使い分けることが重要です。ローカル変数はスクリプト内で完結する処理に適しており、環境変数は他のスクリプトやプロセスと情報を共有する際に活躍します。
また、環境変数は通常、ターミナルを閉じるとリセットされるため、必要に応じて再設定が必要です。
ローカル変数を使う場面
- スクリプト内だけで使用する値。
- 一時的な計算や処理の中間結果を格納。
- 他のスクリプトやプロセスに影響を与えたくない場合。
num1=10
num2=20
result=$((num1 + num2))
echo "合計: $result"
環境変数を使う場面
- システム全体で共有する設定値(例: PATH)。
- 外部コマンドやスクリプトで利用する値。
- 一度設定した値を複数のスクリプトで利用したい場合。
export DATABASE_URL="mysql://user:pass@localhost:3306/db"
./run_script.sh # DATABASE_URL を利用
特殊変数とは?
シェルには、特殊変数と呼ばれる特別なパラメータが用意されています。
特殊変数 「$0(ゼロ)」
# 起動中シェルスクリプト名を取得
echo "$0"
1 2 | [root@CentOS7 bin]# echo "$0" -bash |
特殊変数「$0」は、起動されたシェルスクリプト名を参照します。シェルスクリプトを用いず直接コンソール上で実行した場合、「$0」はスクリプト名ではなく、呼び元シェルの名前になります。今回の場合は、Linuxの標準シェル「bash」が表示されています。
特殊変数「$@」
特殊変数「$@」は、シェルスクリプトやシェル関数の引数すべてをそのまま参照します。
「$@」をダブルクォートで括ると、引数をそれぞれ1個ずつダブルクォートで囲んで展開します。
#!/bin/sh
# 展開後の引数の数を数える
count=0
for arg in "$@"
do
echo "$arg"
count=$(expr $count + 1)
done
echo "展開後の引数の数は${count}です。"
1 2 3 4 | [root@CentOS7 bin]# sh func.sh 引数1 引数2 引数1 引数2 展開後の引数の数は2です。 |
結果として、引数の数は「"引数1" "引数2"」2つとして展開されています。
特殊変数「$*」
特殊変数「$*」は、シェルスクリプトやシェル関数の引数すべてを1つに連結して参照します。
「$*」をダブルクォートで括ると、引数全体を1個のダブルクォートで囲んだ状態に展開します。
#!/bin/sh
# 展開後の引数の数を数える
count=0
for arg in "$*"
do
echo "$arg"
count=$(expr $count + 1)
done
echo "展開後の引数の数は${count}です。"
1 2 3 | [root@CentOS7 bin]# sh func.sh 引数1 引数2 引数1 引数2 展開後の引数の数は1です。 |
結果として、引数の数は「"引数1 引数2"」1つとして展開されています。
思わぬトラブルを避けるために、スクリプト作成時の引数制御には「$*」ではなく、「$@」を使用しましょう。
特殊変数「$#」
特殊変数「$#」は、シェルスクリプトやシェル関数の引数の個数を参照します。
#!/bin/sh
# 引数の入力数を数える
echo "$#"
1 2 | [root@CentOS7 bin]# sh func.sh 引数1 引数2 2 |
特殊変数「$?」
特殊変数「$?」は、「コマンド実行時の終了ステータス」を表わす変数です。
#!/bin/sh
# 「コマンド実行時の終了ステータス」を取得する
exit 255
1 2 3 4 | [root@CentOS7 bin]# sh func.sh func.sh [root@CentOS7 bin]# echo $? 255 |
直接コンソール上で「exit」コマンドを実行すると、コンソール自体が閉じてしまいますので注意してください。
特殊変数「$!」
特殊変数「$!」は、「&」を使ってコマンドをバックグラウンドで走らせた場合に、そのコマンドのプロセスIDがこの「$!」にセットされます。
# バッググラウンドプロセスのPIDを取得する
$ echo "$!"
1 2 3 4 | [root@CentOS7 bin]# sleep 15 & [1] 15995 [root@CentOS7 bin]# echo $! 15995 |
特殊変数「$$」
特殊変数「$$」は、現在動作しているコマンドの「プロセスID」がセットされます。
#!/bin/sh
# 実行中のプロセスIDを取得する
echo "このスクリプトの実行PIDは$$です。"
1 2 | [root@CentOS7 bin]# sh func.sh このスクリプトの実行PIDは15663です。 |
特殊変数「$-」
特殊変数「$-」は、そのシェルの起動時のフラグや、「set」コマンドを使って設定したフラグの一覧がセットされています。
#現在 の オプション フラグを表示する
$ echo $-
1 2 | [root@CentOS7 bin]# echo $- himBH |
特殊変数「$_」
特殊変数「$_」は、直前に実行したコマンドの最後の引数を参照します。
# 直前に実行したコマンドの最後の引数を取得する
$ echo $_
1 2 3 | [root@CentOS7 bin]# sh func.sh 引数1 引数2 [root@CentOS7 bin]# echo $_ 引数2 |