【Shell】シェル ~ 基本編・ループ while / for etc ~

■ はじめに

https://dk521123.hatenablog.com/entry/2015/02/20/001600

より分冊。

シェルのループについて、メモっておく。

目次

【1】while
 1)構文
【2】for
 1)構文
 2)サンプル
  例1:規定回数ループする
  例2:拡張子「.sql」のファイル一覧表示
【3】until
 1)構文
【4】その他事項
 1)continue
 2)break
 3)cat

【1】while

* 条件が真である間、処理を繰り返す

1)構文

while [ 条件 ]
do
  処理
done

【2】for

1)構文

for 変数 in 引数1 引数2do
  処理
done

逆順の場合 (tacコマンドを利用)

# tacコマンド については、後述「【4】その他事項」の「3)cat」を参照
for 変数 in 引数1 引数2do
  処理
done | tac

2)サンプル

例1:規定回数ループする

#!/bin/bash

for((i=0; i<10; i++))                                                      
do
  echo ${i}
done

https://hacknote.jp/archives/54054/

例2:拡張子「.sql」のファイル一覧表示

#!/bin/bash

list=(3.7.9 3.8.0 3.9.6 3.10.14)
for value in ${list[@]} ;
do
  echo "value=$value"
done

echo "*************"

for value in ${list[@]} ;
do
  echo "value=$value"
done | tac

length=${#list[@]}
# 4
echo $length

例3:拡張子「.sql」のファイル一覧表示

#!/bin/sh

for file in `ls ./*.sql`;
do
  echo "Result = ${file}."
done

【3】until

* 条件が偽である間、処理を繰り返す 

1)構文

until [ 条件 ]
do
  処理
done

【4】その他事項

* プログラムである以下の事項は、シェルでもできる。

1)continue

https://xtech.nikkei.com/it/article/COLUMN/20060228/231135/

#!/bin/bash

for((i=0; i<10; i++))                                                      
do
  if [ ${i} -ne 5 ]; then
    echo "Not 5 is ${i}"
    continue
  fi
  echo "GO GO GO ${i}"
done

出力結果

Not 5 is 0
Not 5 is 1
Not 5 is 2
Not 5 is 3
Not 5 is 4
GO GO GO 5
Not 5 is 6
Not 5 is 7
Not 5 is 8
Not 5 is 9

2)break

https://xtech.nikkei.com/it/article/COLUMN/20060228/231133/

#!/bin/bash

for((i=0; i<10; i++))                                                      
do
  if [ ${i} -ne 5 ]; then
    echo "Not 5 is ${i}"
    break
  fi
  echo "GO GO GO ${i}"
done

出力結果

Not 5 is 0

3)tacコマンド

* 入力の行で逆順にして出力する
 => 繰り返しの逆にする場合に利用
 => catコマンドの逆だから「tac」コマンド

https://hydrocul.github.io/wiki/commands/tac.html
逆順の場合 (tacコマンドを利用)

for 変数 in 引数1 引数2do
  処理
done | tac

4)使用上の注意

* 多重ループでbreak (多分、continueも)を使った場合、
 プログラム言語と違い、上位のループまで抜けられない

https://stackoverflow.com/questions/57948914/breaking-out-of-a-nested-loop-in-bash
サンプル

#!/bin/bash

YEAR_LIST=(2023 2024)
MONTH_LIST=(01 02 03 04 05 06 07 08 09 10 11 12)
CURRENT_DATE=`date +"%Y%m%d"`

for year in ${YEAR_LIST[@]};
do
  echo "[DEBUG] target_year=$year"
  for month in ${MONTH_LIST[@]};
  do
    echo "[DEBUG] target_month=$month"
    end_day=`date  +"%d" -d "-1 days + 1 month $(date -d '-1 days + 1 month 2024/11/1' +%Y%m01)"`
    for((i=1; i<=end_day; i++))
    do
      day=`printf "%02d\n" ${i}`
      target_date=${year}${month}${day}
      echo "target_date=${target_date}"
      if [ "${target_date}" -gt "${CURRENT_DATE}" ]; then
         echo "target_date [${target_date}] is greater than ${CURRENT_DATE}"
         break
      fi
    done
    # ★重要★
    if [ "${target_date}" -gt "${CURRENT_DATE}" ]; then break; fi
  done
  # ★重要★
  if [ "${target_date}" -gt "${CURRENT_DATE}" ]; then break; fi
done

echo "Done"

関連記事

シェル ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2014/10/23/005406
シェル ~ 基本編・構文全般 ~
https://dk521123.hatenablog.com/entry/2015/02/20/001600
シェル ~ 基本編・条件分岐 if / case ~
https://dk521123.hatenablog.com/entry/2015/05/01/000043