doループとCaseステートメントを使用してBashでメニューベースのスクリプトを作成する

doループとCaseステートメントを使用してBashでメニューベースのスクリプトを作成する

AWSのtxtファイルからjsonファイルを生成するためのbashスクリプトを作成しようとしています。以下のスクリプトはcase最初のオプションで失敗します。$opt包括変数があるためです。基本的に終了番号を入力すると終了するようにしたいと思います。他の有効な番号のファイルを生成します。その番号が無効な場合は、追加オプションの入力を求められます。

#!/bin/bash

clear

# define variables
NOW=$(date +%F-%a-%H.%M) # year-month-date-day-hour.minute format

# display region list menu
region=($(aws ec2 describe-regions | jq -r '.Regions[].RegionName'))
aws ec2 describe-security-groups --region $region | jq -r '.SecurityGroups[].GroupId' > $region.txt
PS3="Select Region number: "
select opt in "${region[@]}" "exit"
do
   case $opt in
       $opt)
          aws ec2 describe-security-groups --region $region | jq -r '.SecurityGroups[].GroupId' > $region.txt
       # read security groups file into array and create individual json files
       mkdir -p "$region"
       while read group; do
         echo "Processing group: $group"
          aws ec2 describe-security-groups --region $region --group-ids "$group" > "$region"/"$group-"$DATE".json"
       done < $region.txt
           break
          ;;
          "exit")
       echo "Exiting..."
          exit
          ;;
          *)
       echo "Invalid option, try again..."
   esac
done

# cleanup security group text file
rm $region.txt

予想される動作は、1〜14の間の数字を入力し、セキュリティグループjsonファイルがゾーン名を持つディレクトリに作成されることです。この部分はうまくいきます。しかし、終了するために15を入力すると、これが発生します。

Select Region number: 15
Processing group: sg-4fec0526

また、16のように誤った数字を入力すると、15でも同じ現象が発生します。

Select Region number: 16
Processing group: sg-4fec0526

数字 15 を終了する必要があり、1 から 15 以外の数字には Invalid... というメッセージが表示され、別の数字を入力するように求められます。

なぜメニューですか?今は細かい制御が欲しい

答え1

caseおっしゃるように問題は陳述です。定義に応じて、すべての変数は常に自分と一致するため、常にtrueです。

case $opt in
   $opt)
     . . . 

したがって、どの値を指定しても常に同じcaseブロックを実行します。何をしたいのか分かりませんが、私は考えるあなたの目標は次のとおりです。

#!/bin/bash

## Enable extended globbing for the +(...) pattern
shopt -s extglob
clear
# define variables
NOW=$(date +%F-%a-%H.%M) # year-month-date-day-hour.minute format

# display region list menu
region=($(aws ec2 describe-regions | 
    jq -r '.Regions[].RegionName'))
aws ec2 describe-security-groups --region "$region" | jq -r '.SecurityGroups[].GroupId' > "$region.txt"
PS3="Select Region number: "

## make a dummy array which includes the values
validOptions=${region[0]};
for ((i=1; i<${#region[@]}; i++)); do
        validOptions="$validOptions|${region[i]}"
done

select opt in "${region[@]}" "exit"
do
   case $opt in
        ## This uses bash's +(pat1|pat2) syntax which matches
        ## one or more of the |-separated strings.
        +($validOptions))
            echo "Valid!"
            aws ec2 describe-security-groups --region "$region" | 
                jq -r '.SecurityGroups[].GroupId' > "$region.txt"
        # read security groups file into array and create
        # individual json files
        mkdir -p "$region"
        while read group; do
            echo "Processing group: $group"
            aws ec2 describe-security-groups --region "$region" --group-ids "$group" > "${region}/${group}-${DATE}.json"
        done < "$region.txt"
        break
        ;;
    "exit")
        echo "Exiting..."
        exit
        ;;
    *)
        echo "Invalid option $opt, try again..."
   esac
done

関連情報