シェルスクリプト分岐・ループ構文例
概要
Linux 上で便利な機能やマクロ的に処理を行うためにシェルスクリプトを記述することがある。
その中でも比較的よく見かける分岐・ループ構文をメモ。
ファイル状態によって操作を変える
テストコマンドでファイルの状態を確認できる。他にも様々なことができる。詳しくは下記参照。
Linuxコマンド集 - 【 test 】 条件式の真偽を判定する:ITpro
if [ -e 'aaa.txt' ]; then # ファイル aaa.txt が存在するかどうか echo 'exist' # 存在するならexist出力 fi
条件満たす場合・満たさない場合の処理実行
if [ -e 'aaa.txt' ]; then # ファイル aaa.txt が存在かどうか echo 'exist' # 存在するならexist出力 else echo 'not found' # 存在しないならnot found出力 fi
複数条件および処理実行
if [ -s 'aaa.txt' ]; then # ファイル aaa.txt が存在して空ファイルでない場合 echo 'size not 0' # 存在して空ファイルでないならsize not 0出力 elsif [ -e 'aaa.txt' ]; # ファイルが存在するかどうか echo 'empty' # 空ファイルが存在するならempty出力 else echo 'not found' # ファイルが存在しないならnot found出力 fi
exitコードを利用した処理分岐
bash ではexitコードが0なら真、そうでなければ偽となる。これらを利用して &&, || を利用して分岐を書ける。
- && は直前のステータスが 0 なら次を実行
- || は直前のステータスが 0 以外なら次を実行
なお、「{」「}」はコマンドのグループ化であり、各文字前後にはスペース必要。「}」の直前コマンドにはセミコロンが必要。
{ [ -s 'aaa.txt' ] && echo 'size not 0'; } || { [ -e 'aaa.txt' ] && echo 'exist'; } || echo 'not found'
上記を branch.sh として作成してテストすると下記のように出力内容が変化する。
$ rm aaa.txt # ファイルが存在しないようにする rm: 'aaa.txt' を削除できません: No such file or directory $ . branch.sh not found $ touch aaa.txt # サイズ 0 のファイル作成 $ . branch.sh exist $ echo "aaa" >> aaa.txt # ファイルに aaa を追加してサイズを増やす $ . branch.sh size not 0
変数の中身に応じて操作を変更する
NUM=100 case $NUM in # NUMの値が 100) echo 'ok';; # 100 なら 0) echo 'not work';; # 0 なら *) echo '???';; # それ以外 esac
ある範囲の数値に対する操作
SUM=0 for NUM in `seq 1 100`; do # 1-100までに対して操作 SUM=`expr $SUM + $NUM` # 加算 done echo $SUM # 結果出力
bashならば以下の記法が使える。
SUM=0 for ((i=1; i<=100; i++)) do SUM=`expr $SUM + $i` done echo $SUM
ある条件を満たすまで操作する
合計が5000超えるまで計算。
SUM=0 NUM=0 while [ $SUM -lt 5000 ] && NUM=`expr $NUM + 1`; do SUM=`expr $SUM + $NUM` done echo $SUM # 合計値
引数に END が出るまで引数を出力する
while [ -n "$1" ] && [ "$1" != "END" ]; do # 現在処理中の引数が空文字でも END でもないなら処理を行う echo "$1" # 位置パラメータ1番目出力 shift # 位置パラメータをシフト done
シェル引数に対する処理
# シェル引数は何もしなければ位置パラメータに入っている for ARG in "$@"; do # 各位置パラメータに対して操作 echo "$ARG" # 出力 done
標準入力から各要素を取り出し操作
区切り文字としてカンマ(,)が使われた場合の例
read INPUT # このコマンドで入力待ちになる IFS=',' # 区切り文字の指定 set -- $INPUT # 位置パラメータに入力内容をセット for ELEMENT in "$@"; do # それぞれに対して操作 echo "$ELEMENT" done
特定ファイル群に対する操作
for FILE in *.txt; do # カレントディレクトリのテキストファイルに対して操作 echo "$FILE" # ファイル名出力 done
直前のコマンド処理結果を操作
cat 'aaa.txt' | grep "AAA" | while read LINE; do # aaa.txt 内にある AAA が存在する行に対して操作 echo "$LINE" # 内容出力 done
ファイル各行に対する処理
IFS=',' # 区切り文字指定。今回はCSVを処理するためカンマ指定 while read LINE; do # 一行読み込み set -- $LINE # 位置パラメータに一行情報セット echo "(1)$1, (2)$2, (3)$3" # 各列情報出力 done < 'test.txt' # 読み込むファイルはリダイレクトで受け取る