10

When I use break in an if loop in bash it tells me its not valid for bash, what can I use instead?

The use case is, the user is asked a question and if he answers 'no', the script should skip to the next section.

if [[ $ans1_1 = "y" ]]; then
    fedoraDeps
elif [[ $ans1_1 = "n" ]]; then
    break
else
    echo "Answer 'y' or 'n' "
fi
1
  • Yes it would be usefull to not check all conditions of the "if elif ..elif else fi" pattern in some cases, for example when conditions are using the file-system. Commented Jun 9, 2021 at 0:03

4 Answers 4

22

if statements are not "loops", so it doesn't make sense to break out of them. If you want one of your blocks to be a no-op, you can use the built-in : command, which simply does nothing:

if [[ $ans1_1 = y ]]; then
    fedoraDeps
elif [[ $ans1_1 = n ]]; then
    :
else
    echo "Answer 'y' or 'n'"
fi
Sign up to request clarification or add additional context in comments.

1 Comment

What make sense is to avoid testing all conditions of an if then elif elif ... fi construct in some conditions, like when conditions are calling the file-system.
5

For this example, I think it makes more sense to use case.

case $ans1_1 in
    y)fedoraDeps;;
    n);;
    *) echo "Answer 'y' or 'n'";;
esac

From man bash:

If the ;; operator is used, no subsequent matches are attempted after the first pattern match.

1 Comment

This looks cleaner and easier to maintain. I'll update my script to use cases instead. Thanks
1

I agree that case is probably best. But you should probably cast to upper/lower case either way. For the way you had it:

if [[ ${ans1_1,,} = "y" ]]; then
   fedoraDeps
elif [[ ${ans1_1,,} = "n" ]]; then
   :
else
   echo "Answer 'y' or 'n' "
fi

Or, if you wanted uppercase ${ans1_1^^}

Comments

0

This sounds like an ideal case for the select command:

PS3="Please make a selection   >"
select foo in 'y' 'n'; do
    case $foo in
        'Y')
            fedoraDeps
            ;;
        'y')
            fedoraDeps
            ;;
        'n')
            break
            ;;
     esac
done

5 Comments

But doesn't that mean that instead of a normal y/n input, the user will instead have to enter 1 for yes and 2 for no? That seems needlessly complicated for this purpose.
In fairnesss, 1 or 2 is no more or less complicated than y or n, but if the goal is to keep asking until a valid selection is made, select is one of the best tools for the job.
Being presented with 1) y and 2) n, and having to type 1 or 2 rather than y or n, is certainly more complicated just simply typing y/n. I don't see how you can feel otherwise.
break makes only sense in loops... if and case are no loops. use : (does nothing) instead or at case you can resp. should simply remove the break-line.
btw: as @Coder-guy already briefly mentioned in his answer, i would use case "${foo,,}" in to prevent having to maintain 2 identical cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.