====== 01 Bash - 制御文 ======
===== if文 =====
if文は、ある条件を指定して、それが真(0)が偽(1)かで処理を分岐する制御文です。\\
※else、elifは省略可能です。thenは必須となります。
==== 構文 ====
if [ 条件1 ]; または if test 条件
then
条件1が成立した時に実行するコマンド
elif [ 条件2 ];
then
条件1が不成立で条件2が成立した時に実行するコマンド
else
条件1と条件2が不成立の時に実行するコマンド
fi
==== if文 使用例 ====
testコマンドによる、if分岐
test01.sh
#!/bin/sh
if test $1 -le 0
then
echo "Number is Less than or equal 0."
else
echo "Number is grater than 0."
fi
実行例
$ sh test01.sh 6
Number is Less than or equal 0.
$ sh test01.sh 8
Number is grater than 0.
===== 条件 =====
^ ファイル形式のチェック ^^
|-b File|指定したFileがブロックデバイスファイルなら真である。 |
|-c File|指定したFileがキャラクタデバイスファイルなら真である。|
|-d File|指定したFileがディレクトリなら真である。|
|-f File|指定したFileが通常ファイルなら真である。|
|-L File|指定したFileがシンボリックリンクなら真である。|
|-p File|指定したFileが名前付きパイプなら真である。|
|-S File|指定したFileがソケットなら真である。|
^ ファイルパーミッションのチェック ^^
|-g File|指定したFileにSGIDがセットされていれば真である。|
|-k File|指定したFileにスティッキービットがセットされていれば真である。|
|-r File|指定したFileが読み取り可能なら真である。|
|-u File|指定したFileにSUIDがセットされていれば真である。|
|-w File|指定したFileが書き込み可能なら真である。|
|-x File|指定したFileが実行可能なら真である。|
^ その他のファイルのチェック ^^
|-e File|指定したFileが存在すれば真である。|
|-s File|指定したFileのファイルサイズが0より大きければ真である。|
^ 文字列のチェック ^^
|-n 文字列|文字列の長さが0より大きければ真である。|
|-z 文字列|文字列の長さが0であれば真である。|
|文字列1 = 文字列2|2つの文字列が等しければ真である。|
|文字列1 != 文字列2|2つの文字列が等しくなければ真である。|
^ 数値のチェック ^^ 英語略の意味 ^
|数値1 -eq 数値2|2つの数値が等しければ真である。|equal to|
|数値1 -ne 数値2|2つの数値が等しくなければ真である。|not equal to|
|数値1 -ge 数値2|数値1が数値2以上であれば真である。|greater than or equal to|
|数値1 -gt 数値2|数値1が数値2より大きいのであれば真である。|greater than|
|数値1 -le 数値2|数値1が数値2以下であれば真である。|less than or equal to|
|数値1 -lt 数値2|数値1が数値2未満であれば真である。|less than|
^ 論理結合 ^^
|!条件|条件が偽であれば真である。|
|条件1 -a 条件2|条件1と条件2の両方が真であれば真である。(AND)|
|条件1 -o 条件2|条件1と条件2のどちらかが真であれば真である。(OR)|
===== for文 =====
for文は、同一の処理を何度も繰り返すループ文です。\\
引数の要素を順番に変数に渡していく事で、繰り返し処理に変化を付けます。\\
引数の要素がひととおり巡ったらforループを抜けます。\\
ループの回数は引数の要素数で決まります。
==== 構文 ====
for 変数 in 引数・・・
do
繰り返し実行されるコマンド
done
==== for文 例1 ====
for_test01.sh
#!/bin/sh
for i in 0 1 2 3 4 5
do
echo $i
done
実行例
$ ./for_test01.sh
0
1
2
3
4
5
===== for文(C言語風) =====
bashではC言語で同じみの形式でfor文が使えます。\\
expr1を前提とし、条件expr2が成立するまで処理を繰り返し、その間expr3を実行するという形式です。
==== 構文 ====
for (( expr1 ; expr2 ;expr3 ))
do
繰り返し実行されるコマンド
done
==== for文(C言語風) 例1 ====
変数iを0として変数iが10より小さい間変数iに1づつ足していく。
for _test02.sh
#!/bin/sh
for (( i=0 ; i<10 ; i++ ))
do
echo $i
done
実行例
$ ./for_test02.sh
0
1
2
3
4
5
6
7
8
9
===== while文 =====
while文は、ある条件を提示してその条件を満たしている間、同一の処理を何度も繰り返すループ文です。\\
while文は条件の終了状態が真である場合は doとdoneの間に記述されたコマンドを実行します。\\
そして条件の終了状態が偽になり次第ループから抜けます。
==== 構文 ====
while 条件
do
繰り返し実行されるコマンド
done
==== 無限ループを使う ====
while文を使うと無限ループを簡単に作れます。\\
「いつも真」になるようにしてやれば、いいだけです。
無限ループ記述例
^ 記述例 ^ 説明 ^
|while true; do . . . .|trueコマンドはいつも真(0)を返す|
|while [1]; do . . . .|「test 1」はいつも真(0)を返す|
|while :; do . . . .|コマンドは「何もしない」コマンド。終了コードは真(0)を返す。|
==== while文 使用例 ====
変数Aに1を入れておいて、while文の条件を10以下なら真にしておく\\
変数Aが10以下であれば、「まだ10より小さい」と表示させる。\\
exprで変数Aに1づつ足しているので、変数Aが10になればwhile文を抜ける。
while_test01.sh
#!/bin/sh
A=1
while [ $A -lt 10 ]
do
echo "まだ10より小さい"
A=`expr $A + 1`
done
echo "10を超えました。"
実行例
$ ./while_test01.sh
まだ10より小さい
まだ10より小さい
まだ10より小さい
まだ10より小さい
まだ10より小さい
まだ10より小さい
まだ10より小さい
まだ10より小さい
まだ10より小さい
10を超えました。
=== リモートホストにpingを送り続ける ===
while_test02.sh
#!/bin/sh
HOST="example.jp"
INTERVAL=600
while true
do
echo %%%%%
date
ping -c1 $HOST
echo %%%%%
sleep $INTERVAL
done
実行例 10分おきに実行し続ける。
$ ./while_test02.sh
%%%%%
2006年 6月21日 水曜日 23時28分03秒 JST
PING dynabook.mydomain.co.jp (192.168.1.11): 56 data bytes
64 bytes from 192.168.1.11: icmp_seq=0 ttl=64 time=0.751 ms
--- dynabook.mydomain.co.jp ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.751/0.751/0.751/0.000 ms
%%%%%
%%%%%
2006年 6月21日 水曜日 23時38分03秒 JST
PING dynabook.mydomain.co.jp (192.168.1.11): 56 data bytes
64 bytes from 192.168.1.11: icmp_seq=0 ttl=64 time=0.751 ms
--- dynabook.mydomain.co.jp ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.751/0.751/0.751/0.000 ms
%%%%%
%%%%%
2006年 6月21日 水曜日 23時48分03秒 JST
PING dynabook.mydomain.co.jp (192.168.1.11): 56 data bytes
64 bytes from 192.168.1.11: icmp_seq=0 ttl=64 time=0.751 ms
--- dynabook.mydomain.co.jp ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.751/0.751/0.751/0.000 ms
%%%%%
== while文 ファイルの内容を行単位で読み込む ==
while文を使うと、ファイルからデータを順番に読み込みながら、そのファイルが終了するまでループするという処理ができます。\\
この機能は非常に便利なので覚えておくといいでしょう。
構文(fileから読み込みfileの行が終わるまでループします。)
while read LINE
do
・(ループ処理)
・(ループ処理)
・(ループ処理)
done < file
例
test.txtを一行づつ読み込みechoコマンドで標準出力に出力します。
while_test03.sh
#!/bin/sh
FILE=test.txt
while read LINE
do
echo $LINE
done < $FILE
test.txtの内容は下記のようになっています。
$ cat test.txt
月
火
水
木
金
土
日
実行するとこのように一行ずつ表示されます。
$ ./while_test03.sh
月
火
水
木
金
土
日
===== case文 =====
case文は、文字列がパターンと合致するかによって分岐する制御文です。\\
if文を駆使すれば同様の処理も可能ですが、文字列に対する複数の分岐を考える場合はcase文の方がわかりやすく融通もききます。\\
合致するパターンがあれば、)から;;までに指定されているコマンド行を実行します。\\
通常は、パターンの最後には*(ワイルドカード)を指定し、どのパターンにも合致しなかった場合の処理を書いておきます。\\
case文の終了は綴りを逆さまにしたesacです。
==== 構文 ====
case string in
pattern_1)
commands1
;;
pattern_2)
commands2
;;
esac
==== case文で使用するパターン例 ====
^ 表現の形式 ^ 意味 ^
|string)|stringという文字列そのもの|
|string1|string2)|string1あるいはstring2という文字列|
|str*)|先頭がstrの文字列|
|*str)|末尾がstrの文字列|
|[a-z]*)|先頭がアルファベット小文字|
|[!0-9]*)|先頭が数字以外の文字列|
|[yY]|yかY|
|???)|3文字の文字列|
|*)|すべて|
==== case分 例1 ====
case_test01.sh
#!/bin/sh
case $1 in
[a-z]*)
echo "アルファベット小文字で始まってます。"
;;
[A-Z]*)
echo "アルファベット大文字で始まってます。"
;;
[0-9]*)
echo "数字で始まってます。"
;;
esac
実行例
$ ./case_test01.sh snoopy
アルファベット小文字で始まってます。
$ ./case_test01.sh Apple
アルファベット大文字で始まってます。
$ ./case_test01.sh 1999
数字で始まってます。
==== case文 例2 キーボードからの入力で処理を分ける ====
case_test02.sh
#!/bin/sh
echo -n "Please enter Yes or No _"
read RESPONSE
case $RESPONSE in
[Yy][Ee][Ss]) echo "You answered Yes." ;;
[Nn][Oo]) echo "You ansered No." ;;
*) echo "Please enter Yes or No." ;;
esac
実行例
$ ./case_test02.sh
Please enter Yes or No _Yes
You ansered Yes.
$ ./case_test02.sh
Please enter Yes or No _No
You ansered No.
AAAと入力した場合、どれにも合致しないので、*の行に当てはまる。
$ ./case_test02.sh
Please enter Yes or No _AAA
Please enter Yes or No.
===== select文 =====
select文はbashで追加となった制御文です。\\
項目をリストし、番号を選んで処理させるというメニュー形式の対話的な画面が簡単に作れます。\\
case文でも同じようなメニュー画面を作成することもできますが、大掛かりなスクリプトになってしまいます。\\
select文を使うとメニュー画面を簡単に作成できるメリットがあります。
==== 構文 ====
select variable in menulists
do
commands
done
==== select分 例1 ====
※select文の場合は必ずbashを指定しなければなりません。\\
×#!/bin/sh ○#!/bin/bash
select_test01.sh
#!/bin/bash
select i in Item1 Item2 Item3
do
echo "You entered $i."
done
実行例
$ ./select_test01.sh
1)Item1 ←メニューが現れる
2)Item2
3)Item3
#? 1 ←#?で入力待ちになる。
You entered Item1.
===== continueコマンド =====
for文やwhile文などの処理を途中で中断し、処理をループの先頭に戻すコマンドがcontinueです。\\
書式もbreakコマンドと同じで、いくつ前のループ文の先頭へ戻るかを引数で渡せます。
==== 構文 ====
continue 実行を継続したいループまでの深さ
==== continueコマンド 例1 ====
以下のようにfor文が3つのネストになっている場合2を指定すると"for a"のループから実行を継続します。
#!/bin/sh
for a
do
for b
do
for c
do
if [ $c = redhat ];
then
continue 2
fi
done
done
done
===== breakコマンド =====
for文やwhile文から強制的に抜けるコマンドがbreakコマンドです。\\
もちろんselect文やuntil文からも抜け出せます。\\
continueコマンドがループの先頭に戻るのに対し、breakコマンドはループを抜けます。\\
breakコマンドは、引数がないとループ文を1つだけ抜けます。\\
ネストした複数のループを一挙に抜けたいときは、いくつのループを抜けるかという数を引数として指します。\\
※引数に指定した数値の方がループのネストより多かったときは一番上位のループを抜けますが、エラーにはなりません。
==== 構文 ====
break 抜けたいループの深さ
==== breakコマンド 例1 ====
以下のようにfor文が3つのネストになっている場合3を指定すると全てのループから抜けます。
#!/bin/sh
for a
do
for b
do
for c
do
break 3
done
done
done
{{tag>bash:syntax bash}}