0

I am trying to create a bash script to create json files from a txt file in AWS. The script below is failing (I think) at the first case option. I think it's because I have the $opt variable which is a catch all. Basically I want it to exit if you input the exit number. Create the files for any other valid number, and with an invalid number, ask you for another option.

#!/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

The expected behaviour is that you enter a number from 1-14 and Security Group json files are created into a directory of the region name. This part works. However if you enter 15 to exit this happens;

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

Also if you enter an incorrect number e.g. 16 the same things happens as with 15;

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

Numer 15 should exit and anything not 1-15 should echo out Invalid... and ask you to enter another number.

As for why it's a menu? I want granular control just now

  • 1
    Please edit your question and clarify. We need to know what you expect to happen and what is actually happening. "It fails" is useless since it doesn't tell us what actually happens and we can't run your script unless we have access to an AWS account. And we need to see the output of the aws command you are parsing. Also, as a general rule, why in the world would you make this so hard to use? Why use menus and force your user to type stuff (which is impractical, error prone and means your script can't be automated) instead of passing all options at run time as arguments? – terdon Oct 2 '17 at 9:31
  • Thanks for the edit, but please also add the output of aws ec2 describe-regions | jq -r '.Regions[].RegionName'. You are parsing whatever that command returns so we can't test a working solution for you if you don't show us what you are parsing. – terdon Oct 2 '17 at 10:25
  • It just lists the AWS regions; ap-south-1 eu-west-2 eu-west-1 ap-northeast-2 ap-northeast-1 sa-east-1 ca-central-1 ap-southeast-1 ap-southeast-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2 – eekfonky Oct 2 '17 at 10:27
  • OK, then add that to your question so we can see the format. I mean, your issue is obvious, you're matching $opt to itself, so that will always be true, but we can give you a solution as well as pointing out the error if you give us enough information. For instance, if that command returns strings, why are you expecting to select numbers? – terdon Oct 2 '17 at 10:29
  • I thought that was the error but I don't know how to fix it – eekfonky Oct 2 '17 at 10:30
1

The problem is your case statement, as you said. This is always going to be true since any variable, by definition, always matches itself:

case $opt in
   $opt)
     . . . 

So no matter what value you give it, it will always execute the same case block. I am really not sure what you're trying to do but I think you were aiming for something like this:

#!/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
  • it's displaying; 1) 0 3) 2 5) 4 7) 6 9) 8 11) 10 13) 12 15) exit 2) 1 4) 3 6) 5 8) 7 10) 9 12) 11 14) 13 Select Region number: – eekfonky Oct 2 '17 at 11:06
  • I need it to display; 1) ap-south-1 5) ap-northeast-1 9) ap-southeast-2 13) us-west-1 2) eu-west-2 6) sa-east-1 10) eu-central-1 14) us-west-2 3) eu-west-1 7) ca-central-1 11) us-east-1 15) exit 4) ap-northeast-2 8) ap-southeast-1 12) us-east-2 Select Region number: – eekfonky Oct 2 '17 at 11:07
  • 1
    @eekfonky well, that's the sort of thing you need to put into your question. That way I don't waste my time and yours giving you suboptimal solutions. If you had included the output in your question as I asked and explained what you expected to see, I would have given you something useful from the beginning. I'll try and edit this later today but I need to get back to work now. – terdon Oct 2 '17 at 11:36
  • @eekfonky see update. It should be what you need now. – terdon Oct 2 '17 at 16:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.