シェルスクリプト ファイル読み込んで1行ずつ実行

https://dev.classmethod.jp/articles/waiting-for-your-input-with-read-command/
https://genzouw.com/entry/2023/02/18/084531/3300/
https://qiita.com/MahoTakara/items/87c993c12fb4ddb64b85


仕様:
入力ファイルから1行ずつ読み込む。
空行は処理しない。


引数1 : 開始行番号(デフォルトは1)

ループ処理
- 読み込んだ行に行番号を付与して、表示し、実行するかの確認メッセージを表示する。
- y入力で実行。
- n入力で処理スキップ。
- q入力で処理中断。
- 行番号入力で指定した行へ移動。
- それ以外は確認メッセージを再表示する。


cat <<-'EOF' > ReadAndExecute.txt

# 処理1

systemctl status firewalld
export ORACLE_HOME=/u01/app/oracle/product/12.2.0/dbhome_1
echo $ORACLE_HOME

# 処理2
date "+%Y%m%d"

date '+%Y%m%d'

# 処理3
ls -l 

EOF


nl -b a -v 0 ReadAndExecute.txt
nl -b a -v 1 ReadAndExecute.txt
nl -b a -v 3333 ReadAndExecute.txt


cat <<-'EOF' > ReadAndExecute.sh

#!/bin/bash


# 開始行番号(デフォルト=1)
STARTLINE=${1:-1}

# 入力ファイル名
INPUTFILE=ReadAndExecute.txt


OLDIFS=$IFS
IFS=$'\n'

# 入力ファイル行数
INPUTLINECOUNT=$(wc -l ${INPUTFILE} | awk '{print $1}')

# 指定行番号
GOTOLINE=${STARTLINE}

# echo STARTLINE: $STARTLINE
# echo INPUTLINECOUNT: $INPUTLINECOUNT


while [ "${GOTOLINE}" -ne 0 ] ; do

  for line in $(nl -b a -v 0 ${INPUTFILE}) ; do

    i=$(echo $line | cut -f 1)
    cmd=$(echo $line | cut -f 2)

# echo 
# echo i: $i
# echo cmd: "${cmd}"
# echo "現在行番号 : $((i + STARTLINE ))"
# echo "指定行番号(0は指定なし): ${GOTOLINE}"

    # 初回または行番号指定された場合
    if [ "${GOTOLINE}" -ne 0 ] ; then
      # 現在行番号 < 指定行番号であれば、処理をスキップ
      if [ $((i + STARTLINE )) -lt ${GOTOLINE} ] ; then
        continue
      # 現在行番号 = 指定行番号であれば、GOTOLINEを0にセットして処理を継続
      elif [ $((i + STARTLINE )) -eq ${GOTOLINE} ] ; then
        GOTOLINE=0
      # 現在行番号 > 指定行番号であれば、終了。ここにくることはないはず
      else
        echo "異常 [現在行番号 > 指定行番号となりました]"
        IFS=$OLDIFS
        exit 100
      fi
    fi
    
    # コマンドが空の場合、スキップ
    if [ "${cmd}" == "" ] ; then
# echo "コマンドが空です"
      continue
    fi

    echo "---- [L$((i + STARTLINE))]  ${cmd}"
    
    while read -p "ok? (y/n/q/行番号): " ynq ; do
      case "$ynq" in 
        [ynq]) 
          break
          ;;
        *) 
          if [[ "${ynq}" =~ ^[1-9][0-9]*$ ]]; then
            # 指定行番号が処理範囲内かチェック
            if [ "${ynq}" -ge "${STARTLINE}" -a "${ynq}" -le $((STARTLINE + INPUTLINECOUNT -1)) ] ; then
              echo;echo;
              echo "---- GOTO: ${ynq}";
              GOTOLINE="${ynq}"
              echo;echo;
              break 2;
            fi
          fi
          echo "(y/n/q/行番号)で入力してください" 
          ;;
      esac
    done
    
    if [ "${ynq}" == "q" ]; then
      echo;echo;
      echo "---- stopped.";
      echo;echo;
      IFS=$OLDIFS
      exit 0;
    elif [ "${ynq}" == "n" ]; then
      echo;echo;
      echo "---- skipped." ;
      echo;echo;
      continue;
    fi

    echo;echo;
    eval "${cmd}"
    echo;echo;
    
  done

done

echo;echo;
echo "---- end."
echo;echo;

IFS=$OLDIFS
exit 0

EOF

 

grep "" ReadAndExecute.*

chmod +x ReadAndExecute.sh

./ReadAndExecute.sh

./ReadAndExecute.sh 100