Status Code 303 - See Other

Java, C, C++, C#, Objective-C, Swift, bash, perl, ruby, PHP, Python, Scala, Groovy, Go, DevOps, Raspberry Pi など。情報の誤りや指摘・意見などは自由にどうぞ。

シェルスクリプト分岐・ループ構文例

概要

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'            # 読み込むファイルはリダイレクトで受け取る