8

I have the following code in the middle of a script to confirm whether we want to resume the script or not.

read -r -p "Would you like to continue  [Y/N] : " i
case $i in
        [yY])
                echo -e "Resuming the script";;
        [nN])
                echo -e "Skipped and exit script"
                exit 1;;
        *)
                echo "Invalid Option"
                ;;
esac

I would like to know is there any way to know is there any way to recall the switch-case if the input option is invalid?

Kusalananda
  • 333,661

4 Answers4

15

Do your input in a loop. Exit the loop with break (or exit as the case may be) if you get a valid response from the user.

while true; do
    read -p 'Continue? yes/no: ' input
    case $input in
        [yY]*)
            echo 'Continuing'
            break
            ;;
        [nN]*)
            echo 'Ok, exiting'
            exit 1
            ;;
         *)
            echo 'Invalid input' >&2
    esac
done

As a utility function:

ask_continue () {
    while true; do
        read -p 'Continue? yes/no: ' input        
        case $input in
            [yY]*)
                echo 'Continuing'
                break
                ;;
            [nN]*)
                echo 'Ok, exiting'
                exit 1
                ;;
             *)
                echo 'Invalid input' >&2
        esac
    done
}

A variation of the utility function that allows exiting through EOF (e.g. pressing Ctrl+D):

ask_continue () {
    while read -p 'Continue? yes/no: ' input; do    
        case $input in
            [yY]*)
                echo 'Continuing'
                return
                ;;
            [nN]*)
                break
                ;;
             *)
                echo 'Invalid input' >&2
        esac
    done

    echo 'Ok, exiting'
    exit 1
}

Here, there are three ways out of the loop:

  1. The user enters "yes", in which case the function returns.
  2. The user enters "no", in which case the we break out of the loop and execute exit 1.
  3. The read fails due to something like encountering an end-of-input or some other error, in which case the exit 1 is executed.

Instead of exit 1 you may want to use return 1 to allow tho caller to decide what to do when the user does not want to continue. The calling code may then look like

if ! ask_continue; then
    # some cleanup, then exit
fi
Kusalananda
  • 333,661
8

Why not just repeating the read?

unset i
while [[ ! "$i" =~ ^[yYnN]$ ]]; do read -r -p "Would you like to continue  [Y/N] : " i; done
RudiC
  • 8,969
2

You can do by keeping switch case inside a function.

function testCase ()
{
    read -r -p "Would you like to continue  [Y/N] : " i
    case $i in
        [yY])
            echo -e "Resuming the script";;
        [nN])
            echo -e "Skipped and exit script"
            exit 1;;
        *)
            echo "Invalid Option"
            testCase
            ;;
    esac
}
testCase

If the input is invalid it will recall the function until it gets a valid input.

Siva
  • 9,077
  • 3
    Or until you run into a resource restriction or a maximum recursion depth limit. – Kusalananda Sep 03 '18 at 16:35
  • 8
    I wouldn't count on the shell being able to optimize the tail recursion, and given the usual procedural nature of shell scripts, I'd really suggest writing that loop out. – ilkkachu Sep 03 '18 at 18:33
  • 1
    @Kusalananda If the user gives an incorrect answer to a simple yes/no question so many times you hit the recursion limit, he deserves to have the script crash. – Barmar Sep 03 '18 at 21:45
  • @Barmar A programmer should expect that the user will input anything, whether it's an incorrect answer enough times to hit a recursion limit, or eight gigabytes of null and control codes. Failing on a corner case like this is indicative of bad programming. – forest Sep 04 '18 at 00:47
1
until [ "$i" = "0" ]
do
read -r -p "Would you like to continue  [Y/N] : " i
case $i in
        [yY])
                echo -e "Resuming the script";;
        [nN])
                echo -e "Skipped and exit script"
                exit 1;;
        *)
                echo "Invalid Option"
                ;;
esac
done
GAD3R
  • 66,769