SEワンタンの独学備忘録

IT関連の独学した内容や資格試験に対する取り組みの備忘録

【LPIC102】シェルスクリプトの制御文 LPICで学ぶLinux4


今回は前回に引き続き、シェルスクリプトを扱います。
制御文は通常のプログラミングと同じく分岐やループのことを指します。

検証と条件式

分岐の制御文に入る前に、シェルスクリプト(Linuxコマンド)特有の検証のやり方について確認しておきます。
シェルスクリプトでは検証を行う際に、「test」コマンドを使用します。
test」コマンドでは真の場合に「0」を偽の場合に「0以外」を返却します。

test 条件文

また検証は「[]」コマンドをによっても実行することができます。

[ 条件文 ]

よく言われていることですが、「[」と「]」はあくまでコマンドとして扱われるので制御文との間にスペースをいれるのが必須になっています。
if文の制御文の中に組み込んだとき、通常のプログラミング言語と見た目的には似たような形になりますが、あくまでtestコマンドと同等の働きをしているということを念頭に置いておくとエラー発生時などに解決が早くなるのではないかと思います。

以下に主要な条件式を列挙しますが、これをそのまま覚えようとするのはなかなか辛いところでしょう。

■ファイル形式の検証
ファイル形式の検証では指定したファイルが、通常ファイルかディレクトリかなどファイルの形式が一致している場合に真を返します。

条件式 検証内容
-f ファイル 通常ファイルがあるか
-d ディレクトリ ディレクトリがあるか
-r ファイル 読み込み可能なファイルがあるか
-w ファイル 書き込み可能なファイルがあるか
-x ファイル 実行可能なファイルがあるか
-s ファイル サイズが0より大きいファイルがあるか
-L ファイル シンボリックリンクであるファイルがあるか

■ファイル特性の検証
-e」を条件式にした場合、ファイルの形式を問わずファイルでもディレクトリでもいいから存在することを検証することになります。※いまいち使用シーンが思いつかない
nt」はnew timeでしょうか。

条件式 検証内容
-e ファイル ファイル(ディレクトリ含む)があるか
ファイル1 -nt ファイル2 ファイル1がファイル2より新しいか
ファイル1 -ot ファイル2 ファイル1がファイル2より古いか

■数値の検証
シェルスクリプトでは数値の検証に使う等号、不等号などは一般的な記号ではなくオプションの様な形で指定します。
この辺は今回勉強するまであまり認識していませんでした。
一見分かりにくいですが、イコールの「e」を追っていけばなんとかなりそうな感じ。

条件式 検証内容
数値1 -eq 数値2 数値1と数値2が等しいか
数値1 -ge 数値2 数値1が数値2以上(≧)か
数値1 -gt 数値2 数値1が数値2より大きいか
数値1 -le 数値2 数値1が数値2以下(≦)か
数値1 -lt 数値2 数値1が数値2より小さいか
数値1 -ne 数値2 数値1が数値2が等しくないか

■文字列の検証
一般的な文字列(String)に対する検証。

条件式 検証内容
-n 文字列 文字列の長さが0より大きいか
-z 文字列 文字列の長さが0であるか
文字列 = 文字列 2つの文字列が等しいか
文字列 != 文字列 2つの文字列が等しくないか

■論理演算子

一般的なANDやORなどの表現。

条件式 検証内容
! 条件 条件式が偽であるか
条件1 -a 条件2 両条件が真であるか
条件1 -o 条件2 いずれかの条件が真であるか


おまけ:コマンドラインでの実行

これらの条件式はあくまでコマンドの一つでもあるのでコマンドライン上でも実行することができます。
実践的にはコマンドライン上ではあまり使う機会はない気がしますが。

・shell_test.shのファイルがカレントディレクトリに存在するか

[wantan@localhost lpic2]$ test -f shell_test.sh; echo $?
0

・shell_testXX.shのファイルがカレントディレクトリに存在するか

[wantan@localhost lpic2]$ test -f shell_testXX.sh; echo $?
1

また、「[ ]」を用いることでも同様の結果が得られます。

[wantan@localhost lpic2]$ [ -f shell_test.sh ]; echo $?
0
[wantan@localhost lpic2]$ [ -f shell_testXX.sh ]; echo $?
1

条件分岐

ここからは一般的な分岐やループなどの制御文を扱います。

if文

シェルスクリプトにおける条件分岐は「if」文により実行します。
書式は以下の通りです。

if 条件式
        then
                真の場合の実行文
        else
                偽の場合の実行文
fi

・サンプルスクリプト

適当に条件式を当てはめてスクリプトを作成してみます。

#!/bin/bash
#引数が入力されているか判定する

#先頭行は以下の文と等価
#if test -n "$1"
if [ -n "$1" ]
        then
                echo "検証結果は真"
        else
                echo "検証結果は偽"
fi

・実行結果

[wantan@localhost lpic2]$ source if_test.sh
検証結果は偽
[wantan@localhost lpic2]$ source if_test.sh wantan
検証結果は真

不要であればelse部は省略でき、条件を追加したい場合には「elif」文により追加します。

・サンプルスクリプト2

#!/bin/bash

if [ -z "$1" ]
        then
                echo "入力がないので終了します。"
                exit
fi

if [ 'wantan' = $1 ]
        then
                echo "ユーザ名"
        elif [ 'pass' = $1 ]
        then
                echo "パスワード"
        else
                echo "意味のない入力"
fi
case文

シェルスクリプトの条件分岐には「case」文も用意されています。
分岐の条件が多くなる場合にはこちらを使用した方が可読性などの観点から好まれると思われます。

・書式

casein
        値1)
                実行文;;
        値2)
                実行文;;
esac

値と実行文は任意の個数だけ増やすことができます。
また、「)」や「;;」の記号が個人的に忘れやすい。

・サンプルスクリプト

#!/bin/bash

case $1 in
        'wantan')
                echo 'ユーザ名';;
        'pass')
                echo 'パスワード';;
        'file')
                echo 'ファイル名';;
esac

・実行例

[wantan@localhost lpic2]$ ./case_test.sh wantan
ユーザ名
[wantan@localhost lpic2]$ ./case_test.sh pass
パスワード
[wantan@localhost lpic2]$ ./case_test.sh TTTTT
[wantan@localhost lpic2]$

繰り返しの制御文

for文

多くの言語でも使用される一般的な繰り返しの制御文である「for」文はシェルスクリプトでも共通となります。

・書式

for 変数名 in 任意のリスト
do
        実行文
done

適当にサンプルを作成してみます。

・サンプルスクリプト

#!/bin/bash
#引数を表示していくスクリプト

num=0
for param in $@
do
        num=`expr $num + 1`
        echo "$num引数は$param"
done


・実行例

[wantan@localhost lpic2]$ ./for_test.sh a bb ccc dddd eeeee
第1引数はa
第2引数はbb
第3引数はccc
第4引数はdddd
第5引数はeeeee
while文

こちらも繰り返し文として一般的なwhile文を使用することができます。
while文では条件式が満たされている間ループ処理を繰り返すことができます。

・書式

while 条件式
do
        任意の実行文
done

・サンプルスクリプト

#!/bin/bash

num=0
while [ $num -ne 5 ]
do
        num=`expr $num + 1`
        echo "今は$num番目"
done

・実行例

[wantan@localhost lpic2]$ ./while_test.sh
今は1番目
今は2番目
今は3番目
今は4番目
今は5番目

標準入力を受け付ける

readコマンド

ここは他のプログラム言語などでは同等のものをあまり使わない場合もあるかもしれません。
シェルスクリプトではread文を用いることによりシェルスクリプトの実行中に標準入力を受け付けることができます。

ユーザに入力を促す場合など、シェルスクリプトでは実用度も高いところだと思います。

・書式

read 変数

実際に適当なサンプルを作成してみると早いですが、標準入力を変数の中に格納します。

・サンプルスクリプト

#!/bin/bash

echo '名前を入力してください'
read name

touch "$name".txt
echo 'あなたのファイルを作成しました'


・実行例

[wantan@localhost lpic2]$ ./read_test.sh
名前を入力してください
wantan
あなたのファイルを作成しました
[wantan@localhost lpic2]$ ll
合計 32
-rwxr-xr-x. 1 wantan group1 140 117 02:00 case_test.sh
-rwxr-xr-x. 1 wantan group1 139 117 02:35 for_test.sh
-rwxr-xr-x. 1 wantan group1 238 117 01:50 if_test.sh
-rwxr-xr-x. 1 wantan group1 136 117 03:13 read_test.sh
-rwxr-xr-x. 1 wantan group1 134 113 23:12 shell_test.sh
-rwxr-xr-x. 1 wantan group1  68 113 23:22 shell_test2.sh
-rw-r--r--. 1 wantan group1   0 114 23:37 test.txt
-rw-r--r--. 1 wantan group1  85 117 03:10 testlist.txt
-rw-r--r--. 1 wantan group1   0 117 03:17 wantan.txt
-rwxr-xr-x. 1 wantan group1  94 117 02:59 while_test.sh
[wantan@localhost lpic2]$

またreadコマンドとwhileコマンドを組み合わせることで、ファイルを一行ずつ読み込んでいく処理を実装することもできます。
最後に他のコマンドとも組み合わせてサンプルを作成してみます。

・サンプルスクリプト
読み込むファイルを指定し、一行ずつ読み込みながら処理を実行するスクリプトです。

#!/bin/bash

echo 'ファイル名を入力してください'
read filename

if ! [ -f $filename ]
        then
                echo 'ファイルが存在しません、処理を終了します。'
                exit
fi

echo "*********ファイルの内容************"

num=0
while read param
do
        echo "$num:$param"
        num=`expr $num + 1`
done < $filename

・実行例

[wantan@localhost lpic2]$ ./sample.sh
ファイル名を入力してください
file.txt
ファイルが存在しません、処理を終了します。
[wantan@localhost lpic2]$ ./sample.sh
ファイル名を入力してください
testlist.txt
*********ファイルの内容************
0:第1引数はa
1:第2引数はbb
2:第3引数はccc
3:第4引数はdddd
4:第5引数はeeeee
[wantan@localhost lpic2]$


ーーーーーーーーーーーーーーーーーーーーーーー

今回はここまで。
諸事情につき一旦中断か続きがないかもしれません。

・前回(第三回)
www.wantanblog.com

・次回(第五回)
www.wantanblog.com