Case fallthrough based on if condition

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
10
down vote

favorite
1












I am looking for a way to have fallthrough happen based on an if condition within a case condition in bash. For example:



input="foo"
VAR="1"

case $input in
foo)
if [ $VAR = "1" ]; then

# perform fallthrough

else

# do not perform fallthrough

fi
;;
*)
echo "fallthrough worked!"
;;
esac


In the above code, if the variable VAR is 1, I would like to have the case condition perform fallthrough.







share|improve this question















  • 1




    Small question: Are you trying to jump from if [ $VAR -eq 1 ]; then part of the code to whatever is in *) ? Because that's entirely different from what fallthrough is called, thus making your question phrasing just slightly misleading.
    – Sergiy Kolodyazhnyy
    May 28 at 20:24














up vote
10
down vote

favorite
1












I am looking for a way to have fallthrough happen based on an if condition within a case condition in bash. For example:



input="foo"
VAR="1"

case $input in
foo)
if [ $VAR = "1" ]; then

# perform fallthrough

else

# do not perform fallthrough

fi
;;
*)
echo "fallthrough worked!"
;;
esac


In the above code, if the variable VAR is 1, I would like to have the case condition perform fallthrough.







share|improve this question















  • 1




    Small question: Are you trying to jump from if [ $VAR -eq 1 ]; then part of the code to whatever is in *) ? Because that's entirely different from what fallthrough is called, thus making your question phrasing just slightly misleading.
    – Sergiy Kolodyazhnyy
    May 28 at 20:24












up vote
10
down vote

favorite
1









up vote
10
down vote

favorite
1






1





I am looking for a way to have fallthrough happen based on an if condition within a case condition in bash. For example:



input="foo"
VAR="1"

case $input in
foo)
if [ $VAR = "1" ]; then

# perform fallthrough

else

# do not perform fallthrough

fi
;;
*)
echo "fallthrough worked!"
;;
esac


In the above code, if the variable VAR is 1, I would like to have the case condition perform fallthrough.







share|improve this question











I am looking for a way to have fallthrough happen based on an if condition within a case condition in bash. For example:



input="foo"
VAR="1"

case $input in
foo)
if [ $VAR = "1" ]; then

# perform fallthrough

else

# do not perform fallthrough

fi
;;
*)
echo "fallthrough worked!"
;;
esac


In the above code, if the variable VAR is 1, I would like to have the case condition perform fallthrough.









share|improve this question










share|improve this question




share|improve this question









asked May 28 at 19:07









Smashgen

984




984







  • 1




    Small question: Are you trying to jump from if [ $VAR -eq 1 ]; then part of the code to whatever is in *) ? Because that's entirely different from what fallthrough is called, thus making your question phrasing just slightly misleading.
    – Sergiy Kolodyazhnyy
    May 28 at 20:24












  • 1




    Small question: Are you trying to jump from if [ $VAR -eq 1 ]; then part of the code to whatever is in *) ? Because that's entirely different from what fallthrough is called, thus making your question phrasing just slightly misleading.
    – Sergiy Kolodyazhnyy
    May 28 at 20:24







1




1




Small question: Are you trying to jump from if [ $VAR -eq 1 ]; then part of the code to whatever is in *) ? Because that's entirely different from what fallthrough is called, thus making your question phrasing just slightly misleading.
– Sergiy Kolodyazhnyy
May 28 at 20:24




Small question: Are you trying to jump from if [ $VAR -eq 1 ]; then part of the code to whatever is in *) ? Because that's entirely different from what fallthrough is called, thus making your question phrasing just slightly misleading.
– Sergiy Kolodyazhnyy
May 28 at 20:24










8 Answers
8






active

oldest

votes

















up vote
8
down vote













You can't. The way to have a case fall through is to replace the ;; separator with ;& (or ;;&). And it's a syntax error to put that inside an if.



You could write the whole logic out as a regular conditional:



if [ "$input" != "foo" ] || [ "$VAR" = 1 ]; then
one branch ...
else # $input = "foo" && $VAR != 1
another branch...
fi





share|improve this answer





















  • Yes, He can ! :)
    – Isaac
    May 29 at 8:46










  • @Isaac, well, yeah, though they did specify basing the fallthrough on an if.
    – ilkkachu
    May 29 at 9:10










  • +1 To be clear: I up voted your answer. :).
    – Isaac
    May 29 at 9:16

















up vote
7
down vote













I'd suggest restructuring your logic: put the "fallthrough" code into a function instead:



fallthrough() echo 'fallthrough worked!'; 

for input in foo bar; do
for var in 1 2; do
echo "$input $var"
case $input in
foo)
if (( var == 1 )); then
echo "falling through"
fallthrough
else
echo "not falling through"
fi
;;
*) fallthrough;;
esac
done
done


outputs



foo 1
falling through
fallthrough worked!
foo 2
not falling through
bar 1
fallthrough worked!
bar 2
fallthrough worked!





share|improve this answer




























    up vote
    7
    down vote













    The following script turns your test "inside out" in the sense that we test $var first and then perform the fallthrough (using ;& in a case) depending on $input.



    We do this because the question of whether or not to "perform the fallthrough" is really only dependent on $input if $var is 1. If it's any other value, the question of whether to do the fallthrough does not even have to be asked.



    #/bin/bash

    input='foo'
    var='1'

    case $var in
    1)
    case $input in
    foo)
    echo 'perform fallthrough'
    ;&
    *)
    echo 'fallthough worked'
    esac
    ;;
    *)
    echo 'what fallthrough?'
    esac


    Or, without case:



    if [ "$var" -eq 1 ]; then
    if [ "$input" = 'foo' ]; then
    echo 'perform fallthrough'
    fi
    echo 'fallthough worked'
    else
    echo 'what fallthrough?'
    fi





    share|improve this answer























    • I think you nailed what OP actually wanted, which seems to be jumping from their original if statement to whatever in *). Already have my +1.
      – Sergiy Kolodyazhnyy
      May 28 at 20:26

















    up vote
    5
    down vote













    Not something that I would do, but you could achieve something approaching with:



    shopt -s extglob # for !(*)
    default='*'
    case $input in
    (foo)
    if [ "$VAR" = 1 ]; then
    echo going for fallthrough
    else
    echo disabling fallthrough
    default='!(*)'
    fi ;;&

    ($default)
    echo fallthrough
    esac





    share|improve this answer




























      up vote
      2
      down vote













      Test both variables at once (bash 4.0-alpha+):



      #!/bin/bash
      while (($#>1)); do
      input=$1 VAR=$2
      echo "input=$input VAR=$VAR"; shift 2

      if [ "$VAR" = 1 ]; then new=1; else new=0; fi

      case $input$new in
      foo0) echo "do not perform fallthrough" ;;
      foo*) echo "perform fallthrough" ;&
      *) echo "fallthrough worked!" ;;
      esac

      echo
      done


      On testing:



      $ ./script foo 0 foo 1 bar baz
      input=foo VAR=0
      do not perform fallthrough

      input=foo VAR=1
      perform fallthrough
      fallthrough worked!

      input=bar VAR=baz
      fallthrough worked!


      Clean and simple.



      Understand that the tested value ($new) must have only two possible values, that is why the if clause is there, to transform VAR to a Boolean value. If VAR may be made to be a Boolean, then test for 0 (not 1) in the case and remove the if.






      share|improve this answer






























        up vote
        1
        down vote













        You can make the fallthrough default but place a condition that the code only executes only if the condition is met



        #!/bin/bash

        input='foo'
        var='1'

        case $input in
        foo)
        echo "Do fall through"
        ;& #always fall through
        *)
        if [ $var = "1" ] #execute only if condition matches
        then
        echo "fallthrough took place"
        fi
        esac


        But as ilkkachu suggested you can also use conditions rather than switch.






        share|improve this answer




























          up vote
          1
          down vote













          If you don't mind someone complaining about they don't understand your code, you could simply switch the order of the two conditionals:



          input="foo"
          VAR="1"

          if
          case $input in
          foo)
          [ $VAR = "1" ]
          ;;
          esac
          then
          echo "fallthrough worked!"
          fi


          Or:



          input="foo"
          VAR="1"

          case $input in
          foo)
          [ $VAR = "1" ]
          ;;
          esac &&
          echo "fallthrough worked!"


          Simple and clear (at least to me). case doesn't support fallthrough itself. But you can replace *) with && after esac to make it respect to the return values of other branches.






          share|improve this answer




























            up vote
            -4
            down vote













            New ;& and ;;& operators were introduced in Bash
            4.0
            and although they both might be useful in similar situations I think
            they are of no use in your case. This is what man bash says about
            these operators:




            If the ;; operator is used, no subsequent matches are attempted after
            the first pattern match. Using ;& in place of ;; causes execution to
            continue with the list associated with the next set of patterns. Using
            ;;& in place of ;; causes the shell to test the next pattern list in
            the statement, if any, and execute any associated list on a successful
            match.




            In other words, ;& is a fall through and as we know it from C and
            ;;& makes bash check remaining cases instead of returning from
            case block entirely. You can find a nice example of ;;& in action
            here: https://stackoverflow.com/a/24544780/3691891.



            That being said, neither ;& nor ;;& could be used in your script
            because both of them would go to *) that would be always run.



            The following script works and does what you want without re-arranging
            the logic but consider it only as an example and never rely on it, it's too fragile.
            I've taken the idea from
            here:



            #!/usr/bin/env bash

            function jumpto
            grep -v ':$')
            cmd=$(echo "$cmd"

            input="foo"
            VAR="1"

            case $input in
            foo)
            if [ $VAR = "1" ]; then

            printf "perform fallthroughn"
            jumpto ft
            else
            printf "do not perform fallthroughn"

            fi
            ;;
            *)
            ft:
            echo "fallthrough worked!"
            ;;
            esac





            share|improve this answer





















            • Why a downvote?
              – Arkadiusz Drabczyk
              May 28 at 20:15






            • 1




              This may work in a toy example but it's near-incomprehensible and wouldn't work in a larger script. The way you simulate goto is extremely fragile, and to say that it really simulates goto is an exaggeration. The code returns from the jumpto function and executes whatever comes after it. The fact that this is equivalent to continuing executing after the block between ft: and ;; is a coincidence because jumpto is the last command in the same complex command as the jumped-to block.
              – Gilles
              May 28 at 20:59






            • 1




              OK, I clearly emphasized that in my answer.
              – Arkadiusz Drabczyk
              May 28 at 21:01











            Your Answer







            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "106"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f446537%2fcase-fallthrough-based-on-if-condition%23new-answer', 'question_page');

            );

            Post as a guest






























            8 Answers
            8






            active

            oldest

            votes








            8 Answers
            8






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            8
            down vote













            You can't. The way to have a case fall through is to replace the ;; separator with ;& (or ;;&). And it's a syntax error to put that inside an if.



            You could write the whole logic out as a regular conditional:



            if [ "$input" != "foo" ] || [ "$VAR" = 1 ]; then
            one branch ...
            else # $input = "foo" && $VAR != 1
            another branch...
            fi





            share|improve this answer





















            • Yes, He can ! :)
              – Isaac
              May 29 at 8:46










            • @Isaac, well, yeah, though they did specify basing the fallthrough on an if.
              – ilkkachu
              May 29 at 9:10










            • +1 To be clear: I up voted your answer. :).
              – Isaac
              May 29 at 9:16














            up vote
            8
            down vote













            You can't. The way to have a case fall through is to replace the ;; separator with ;& (or ;;&). And it's a syntax error to put that inside an if.



            You could write the whole logic out as a regular conditional:



            if [ "$input" != "foo" ] || [ "$VAR" = 1 ]; then
            one branch ...
            else # $input = "foo" && $VAR != 1
            another branch...
            fi





            share|improve this answer





















            • Yes, He can ! :)
              – Isaac
              May 29 at 8:46










            • @Isaac, well, yeah, though they did specify basing the fallthrough on an if.
              – ilkkachu
              May 29 at 9:10










            • +1 To be clear: I up voted your answer. :).
              – Isaac
              May 29 at 9:16












            up vote
            8
            down vote










            up vote
            8
            down vote









            You can't. The way to have a case fall through is to replace the ;; separator with ;& (or ;;&). And it's a syntax error to put that inside an if.



            You could write the whole logic out as a regular conditional:



            if [ "$input" != "foo" ] || [ "$VAR" = 1 ]; then
            one branch ...
            else # $input = "foo" && $VAR != 1
            another branch...
            fi





            share|improve this answer













            You can't. The way to have a case fall through is to replace the ;; separator with ;& (or ;;&). And it's a syntax error to put that inside an if.



            You could write the whole logic out as a regular conditional:



            if [ "$input" != "foo" ] || [ "$VAR" = 1 ]; then
            one branch ...
            else # $input = "foo" && $VAR != 1
            another branch...
            fi






            share|improve this answer













            share|improve this answer



            share|improve this answer











            answered May 28 at 20:05









            ilkkachu

            47.8k668131




            47.8k668131











            • Yes, He can ! :)
              – Isaac
              May 29 at 8:46










            • @Isaac, well, yeah, though they did specify basing the fallthrough on an if.
              – ilkkachu
              May 29 at 9:10










            • +1 To be clear: I up voted your answer. :).
              – Isaac
              May 29 at 9:16
















            • Yes, He can ! :)
              – Isaac
              May 29 at 8:46










            • @Isaac, well, yeah, though they did specify basing the fallthrough on an if.
              – ilkkachu
              May 29 at 9:10










            • +1 To be clear: I up voted your answer. :).
              – Isaac
              May 29 at 9:16















            Yes, He can ! :)
            – Isaac
            May 29 at 8:46




            Yes, He can ! :)
            – Isaac
            May 29 at 8:46












            @Isaac, well, yeah, though they did specify basing the fallthrough on an if.
            – ilkkachu
            May 29 at 9:10




            @Isaac, well, yeah, though they did specify basing the fallthrough on an if.
            – ilkkachu
            May 29 at 9:10












            +1 To be clear: I up voted your answer. :).
            – Isaac
            May 29 at 9:16




            +1 To be clear: I up voted your answer. :).
            – Isaac
            May 29 at 9:16












            up vote
            7
            down vote













            I'd suggest restructuring your logic: put the "fallthrough" code into a function instead:



            fallthrough() echo 'fallthrough worked!'; 

            for input in foo bar; do
            for var in 1 2; do
            echo "$input $var"
            case $input in
            foo)
            if (( var == 1 )); then
            echo "falling through"
            fallthrough
            else
            echo "not falling through"
            fi
            ;;
            *) fallthrough;;
            esac
            done
            done


            outputs



            foo 1
            falling through
            fallthrough worked!
            foo 2
            not falling through
            bar 1
            fallthrough worked!
            bar 2
            fallthrough worked!





            share|improve this answer

























              up vote
              7
              down vote













              I'd suggest restructuring your logic: put the "fallthrough" code into a function instead:



              fallthrough() echo 'fallthrough worked!'; 

              for input in foo bar; do
              for var in 1 2; do
              echo "$input $var"
              case $input in
              foo)
              if (( var == 1 )); then
              echo "falling through"
              fallthrough
              else
              echo "not falling through"
              fi
              ;;
              *) fallthrough;;
              esac
              done
              done


              outputs



              foo 1
              falling through
              fallthrough worked!
              foo 2
              not falling through
              bar 1
              fallthrough worked!
              bar 2
              fallthrough worked!





              share|improve this answer























                up vote
                7
                down vote










                up vote
                7
                down vote









                I'd suggest restructuring your logic: put the "fallthrough" code into a function instead:



                fallthrough() echo 'fallthrough worked!'; 

                for input in foo bar; do
                for var in 1 2; do
                echo "$input $var"
                case $input in
                foo)
                if (( var == 1 )); then
                echo "falling through"
                fallthrough
                else
                echo "not falling through"
                fi
                ;;
                *) fallthrough;;
                esac
                done
                done


                outputs



                foo 1
                falling through
                fallthrough worked!
                foo 2
                not falling through
                bar 1
                fallthrough worked!
                bar 2
                fallthrough worked!





                share|improve this answer













                I'd suggest restructuring your logic: put the "fallthrough" code into a function instead:



                fallthrough() echo 'fallthrough worked!'; 

                for input in foo bar; do
                for var in 1 2; do
                echo "$input $var"
                case $input in
                foo)
                if (( var == 1 )); then
                echo "falling through"
                fallthrough
                else
                echo "not falling through"
                fi
                ;;
                *) fallthrough;;
                esac
                done
                done


                outputs



                foo 1
                falling through
                fallthrough worked!
                foo 2
                not falling through
                bar 1
                fallthrough worked!
                bar 2
                fallthrough worked!






                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered May 28 at 19:56









                glenn jackman

                45.7k265100




                45.7k265100




















                    up vote
                    7
                    down vote













                    The following script turns your test "inside out" in the sense that we test $var first and then perform the fallthrough (using ;& in a case) depending on $input.



                    We do this because the question of whether or not to "perform the fallthrough" is really only dependent on $input if $var is 1. If it's any other value, the question of whether to do the fallthrough does not even have to be asked.



                    #/bin/bash

                    input='foo'
                    var='1'

                    case $var in
                    1)
                    case $input in
                    foo)
                    echo 'perform fallthrough'
                    ;&
                    *)
                    echo 'fallthough worked'
                    esac
                    ;;
                    *)
                    echo 'what fallthrough?'
                    esac


                    Or, without case:



                    if [ "$var" -eq 1 ]; then
                    if [ "$input" = 'foo' ]; then
                    echo 'perform fallthrough'
                    fi
                    echo 'fallthough worked'
                    else
                    echo 'what fallthrough?'
                    fi





                    share|improve this answer























                    • I think you nailed what OP actually wanted, which seems to be jumping from their original if statement to whatever in *). Already have my +1.
                      – Sergiy Kolodyazhnyy
                      May 28 at 20:26














                    up vote
                    7
                    down vote













                    The following script turns your test "inside out" in the sense that we test $var first and then perform the fallthrough (using ;& in a case) depending on $input.



                    We do this because the question of whether or not to "perform the fallthrough" is really only dependent on $input if $var is 1. If it's any other value, the question of whether to do the fallthrough does not even have to be asked.



                    #/bin/bash

                    input='foo'
                    var='1'

                    case $var in
                    1)
                    case $input in
                    foo)
                    echo 'perform fallthrough'
                    ;&
                    *)
                    echo 'fallthough worked'
                    esac
                    ;;
                    *)
                    echo 'what fallthrough?'
                    esac


                    Or, without case:



                    if [ "$var" -eq 1 ]; then
                    if [ "$input" = 'foo' ]; then
                    echo 'perform fallthrough'
                    fi
                    echo 'fallthough worked'
                    else
                    echo 'what fallthrough?'
                    fi





                    share|improve this answer























                    • I think you nailed what OP actually wanted, which seems to be jumping from their original if statement to whatever in *). Already have my +1.
                      – Sergiy Kolodyazhnyy
                      May 28 at 20:26












                    up vote
                    7
                    down vote










                    up vote
                    7
                    down vote









                    The following script turns your test "inside out" in the sense that we test $var first and then perform the fallthrough (using ;& in a case) depending on $input.



                    We do this because the question of whether or not to "perform the fallthrough" is really only dependent on $input if $var is 1. If it's any other value, the question of whether to do the fallthrough does not even have to be asked.



                    #/bin/bash

                    input='foo'
                    var='1'

                    case $var in
                    1)
                    case $input in
                    foo)
                    echo 'perform fallthrough'
                    ;&
                    *)
                    echo 'fallthough worked'
                    esac
                    ;;
                    *)
                    echo 'what fallthrough?'
                    esac


                    Or, without case:



                    if [ "$var" -eq 1 ]; then
                    if [ "$input" = 'foo' ]; then
                    echo 'perform fallthrough'
                    fi
                    echo 'fallthough worked'
                    else
                    echo 'what fallthrough?'
                    fi





                    share|improve this answer















                    The following script turns your test "inside out" in the sense that we test $var first and then perform the fallthrough (using ;& in a case) depending on $input.



                    We do this because the question of whether or not to "perform the fallthrough" is really only dependent on $input if $var is 1. If it's any other value, the question of whether to do the fallthrough does not even have to be asked.



                    #/bin/bash

                    input='foo'
                    var='1'

                    case $var in
                    1)
                    case $input in
                    foo)
                    echo 'perform fallthrough'
                    ;&
                    *)
                    echo 'fallthough worked'
                    esac
                    ;;
                    *)
                    echo 'what fallthrough?'
                    esac


                    Or, without case:



                    if [ "$var" -eq 1 ]; then
                    if [ "$input" = 'foo' ]; then
                    echo 'perform fallthrough'
                    fi
                    echo 'fallthough worked'
                    else
                    echo 'what fallthrough?'
                    fi






                    share|improve this answer















                    share|improve this answer



                    share|improve this answer








                    edited May 30 at 19:51









                    Barmar

                    6,6801122




                    6,6801122











                    answered May 28 at 20:18









                    Kusalananda

                    102k13199314




                    102k13199314











                    • I think you nailed what OP actually wanted, which seems to be jumping from their original if statement to whatever in *). Already have my +1.
                      – Sergiy Kolodyazhnyy
                      May 28 at 20:26
















                    • I think you nailed what OP actually wanted, which seems to be jumping from their original if statement to whatever in *). Already have my +1.
                      – Sergiy Kolodyazhnyy
                      May 28 at 20:26















                    I think you nailed what OP actually wanted, which seems to be jumping from their original if statement to whatever in *). Already have my +1.
                    – Sergiy Kolodyazhnyy
                    May 28 at 20:26




                    I think you nailed what OP actually wanted, which seems to be jumping from their original if statement to whatever in *). Already have my +1.
                    – Sergiy Kolodyazhnyy
                    May 28 at 20:26










                    up vote
                    5
                    down vote













                    Not something that I would do, but you could achieve something approaching with:



                    shopt -s extglob # for !(*)
                    default='*'
                    case $input in
                    (foo)
                    if [ "$VAR" = 1 ]; then
                    echo going for fallthrough
                    else
                    echo disabling fallthrough
                    default='!(*)'
                    fi ;;&

                    ($default)
                    echo fallthrough
                    esac





                    share|improve this answer

























                      up vote
                      5
                      down vote













                      Not something that I would do, but you could achieve something approaching with:



                      shopt -s extglob # for !(*)
                      default='*'
                      case $input in
                      (foo)
                      if [ "$VAR" = 1 ]; then
                      echo going for fallthrough
                      else
                      echo disabling fallthrough
                      default='!(*)'
                      fi ;;&

                      ($default)
                      echo fallthrough
                      esac





                      share|improve this answer























                        up vote
                        5
                        down vote










                        up vote
                        5
                        down vote









                        Not something that I would do, but you could achieve something approaching with:



                        shopt -s extglob # for !(*)
                        default='*'
                        case $input in
                        (foo)
                        if [ "$VAR" = 1 ]; then
                        echo going for fallthrough
                        else
                        echo disabling fallthrough
                        default='!(*)'
                        fi ;;&

                        ($default)
                        echo fallthrough
                        esac





                        share|improve this answer













                        Not something that I would do, but you could achieve something approaching with:



                        shopt -s extglob # for !(*)
                        default='*'
                        case $input in
                        (foo)
                        if [ "$VAR" = 1 ]; then
                        echo going for fallthrough
                        else
                        echo disabling fallthrough
                        default='!(*)'
                        fi ;;&

                        ($default)
                        echo fallthrough
                        esac






                        share|improve this answer













                        share|improve this answer



                        share|improve this answer











                        answered May 28 at 21:41









                        Stéphane Chazelas

                        279k53513844




                        279k53513844




















                            up vote
                            2
                            down vote













                            Test both variables at once (bash 4.0-alpha+):



                            #!/bin/bash
                            while (($#>1)); do
                            input=$1 VAR=$2
                            echo "input=$input VAR=$VAR"; shift 2

                            if [ "$VAR" = 1 ]; then new=1; else new=0; fi

                            case $input$new in
                            foo0) echo "do not perform fallthrough" ;;
                            foo*) echo "perform fallthrough" ;&
                            *) echo "fallthrough worked!" ;;
                            esac

                            echo
                            done


                            On testing:



                            $ ./script foo 0 foo 1 bar baz
                            input=foo VAR=0
                            do not perform fallthrough

                            input=foo VAR=1
                            perform fallthrough
                            fallthrough worked!

                            input=bar VAR=baz
                            fallthrough worked!


                            Clean and simple.



                            Understand that the tested value ($new) must have only two possible values, that is why the if clause is there, to transform VAR to a Boolean value. If VAR may be made to be a Boolean, then test for 0 (not 1) in the case and remove the if.






                            share|improve this answer



























                              up vote
                              2
                              down vote













                              Test both variables at once (bash 4.0-alpha+):



                              #!/bin/bash
                              while (($#>1)); do
                              input=$1 VAR=$2
                              echo "input=$input VAR=$VAR"; shift 2

                              if [ "$VAR" = 1 ]; then new=1; else new=0; fi

                              case $input$new in
                              foo0) echo "do not perform fallthrough" ;;
                              foo*) echo "perform fallthrough" ;&
                              *) echo "fallthrough worked!" ;;
                              esac

                              echo
                              done


                              On testing:



                              $ ./script foo 0 foo 1 bar baz
                              input=foo VAR=0
                              do not perform fallthrough

                              input=foo VAR=1
                              perform fallthrough
                              fallthrough worked!

                              input=bar VAR=baz
                              fallthrough worked!


                              Clean and simple.



                              Understand that the tested value ($new) must have only two possible values, that is why the if clause is there, to transform VAR to a Boolean value. If VAR may be made to be a Boolean, then test for 0 (not 1) in the case and remove the if.






                              share|improve this answer

























                                up vote
                                2
                                down vote










                                up vote
                                2
                                down vote









                                Test both variables at once (bash 4.0-alpha+):



                                #!/bin/bash
                                while (($#>1)); do
                                input=$1 VAR=$2
                                echo "input=$input VAR=$VAR"; shift 2

                                if [ "$VAR" = 1 ]; then new=1; else new=0; fi

                                case $input$new in
                                foo0) echo "do not perform fallthrough" ;;
                                foo*) echo "perform fallthrough" ;&
                                *) echo "fallthrough worked!" ;;
                                esac

                                echo
                                done


                                On testing:



                                $ ./script foo 0 foo 1 bar baz
                                input=foo VAR=0
                                do not perform fallthrough

                                input=foo VAR=1
                                perform fallthrough
                                fallthrough worked!

                                input=bar VAR=baz
                                fallthrough worked!


                                Clean and simple.



                                Understand that the tested value ($new) must have only two possible values, that is why the if clause is there, to transform VAR to a Boolean value. If VAR may be made to be a Boolean, then test for 0 (not 1) in the case and remove the if.






                                share|improve this answer















                                Test both variables at once (bash 4.0-alpha+):



                                #!/bin/bash
                                while (($#>1)); do
                                input=$1 VAR=$2
                                echo "input=$input VAR=$VAR"; shift 2

                                if [ "$VAR" = 1 ]; then new=1; else new=0; fi

                                case $input$new in
                                foo0) echo "do not perform fallthrough" ;;
                                foo*) echo "perform fallthrough" ;&
                                *) echo "fallthrough worked!" ;;
                                esac

                                echo
                                done


                                On testing:



                                $ ./script foo 0 foo 1 bar baz
                                input=foo VAR=0
                                do not perform fallthrough

                                input=foo VAR=1
                                perform fallthrough
                                fallthrough worked!

                                input=bar VAR=baz
                                fallthrough worked!


                                Clean and simple.



                                Understand that the tested value ($new) must have only two possible values, that is why the if clause is there, to transform VAR to a Boolean value. If VAR may be made to be a Boolean, then test for 0 (not 1) in the case and remove the if.







                                share|improve this answer















                                share|improve this answer



                                share|improve this answer








                                edited May 30 at 2:13


























                                answered May 29 at 8:46









                                Isaac

                                6,3241633




                                6,3241633




















                                    up vote
                                    1
                                    down vote













                                    You can make the fallthrough default but place a condition that the code only executes only if the condition is met



                                    #!/bin/bash

                                    input='foo'
                                    var='1'

                                    case $input in
                                    foo)
                                    echo "Do fall through"
                                    ;& #always fall through
                                    *)
                                    if [ $var = "1" ] #execute only if condition matches
                                    then
                                    echo "fallthrough took place"
                                    fi
                                    esac


                                    But as ilkkachu suggested you can also use conditions rather than switch.






                                    share|improve this answer

























                                      up vote
                                      1
                                      down vote













                                      You can make the fallthrough default but place a condition that the code only executes only if the condition is met



                                      #!/bin/bash

                                      input='foo'
                                      var='1'

                                      case $input in
                                      foo)
                                      echo "Do fall through"
                                      ;& #always fall through
                                      *)
                                      if [ $var = "1" ] #execute only if condition matches
                                      then
                                      echo "fallthrough took place"
                                      fi
                                      esac


                                      But as ilkkachu suggested you can also use conditions rather than switch.






                                      share|improve this answer























                                        up vote
                                        1
                                        down vote










                                        up vote
                                        1
                                        down vote









                                        You can make the fallthrough default but place a condition that the code only executes only if the condition is met



                                        #!/bin/bash

                                        input='foo'
                                        var='1'

                                        case $input in
                                        foo)
                                        echo "Do fall through"
                                        ;& #always fall through
                                        *)
                                        if [ $var = "1" ] #execute only if condition matches
                                        then
                                        echo "fallthrough took place"
                                        fi
                                        esac


                                        But as ilkkachu suggested you can also use conditions rather than switch.






                                        share|improve this answer













                                        You can make the fallthrough default but place a condition that the code only executes only if the condition is met



                                        #!/bin/bash

                                        input='foo'
                                        var='1'

                                        case $input in
                                        foo)
                                        echo "Do fall through"
                                        ;& #always fall through
                                        *)
                                        if [ $var = "1" ] #execute only if condition matches
                                        then
                                        echo "fallthrough took place"
                                        fi
                                        esac


                                        But as ilkkachu suggested you can also use conditions rather than switch.







                                        share|improve this answer













                                        share|improve this answer



                                        share|improve this answer











                                        answered May 29 at 8:02









                                        yashC

                                        116




                                        116




















                                            up vote
                                            1
                                            down vote













                                            If you don't mind someone complaining about they don't understand your code, you could simply switch the order of the two conditionals:



                                            input="foo"
                                            VAR="1"

                                            if
                                            case $input in
                                            foo)
                                            [ $VAR = "1" ]
                                            ;;
                                            esac
                                            then
                                            echo "fallthrough worked!"
                                            fi


                                            Or:



                                            input="foo"
                                            VAR="1"

                                            case $input in
                                            foo)
                                            [ $VAR = "1" ]
                                            ;;
                                            esac &&
                                            echo "fallthrough worked!"


                                            Simple and clear (at least to me). case doesn't support fallthrough itself. But you can replace *) with && after esac to make it respect to the return values of other branches.






                                            share|improve this answer

























                                              up vote
                                              1
                                              down vote













                                              If you don't mind someone complaining about they don't understand your code, you could simply switch the order of the two conditionals:



                                              input="foo"
                                              VAR="1"

                                              if
                                              case $input in
                                              foo)
                                              [ $VAR = "1" ]
                                              ;;
                                              esac
                                              then
                                              echo "fallthrough worked!"
                                              fi


                                              Or:



                                              input="foo"
                                              VAR="1"

                                              case $input in
                                              foo)
                                              [ $VAR = "1" ]
                                              ;;
                                              esac &&
                                              echo "fallthrough worked!"


                                              Simple and clear (at least to me). case doesn't support fallthrough itself. But you can replace *) with && after esac to make it respect to the return values of other branches.






                                              share|improve this answer























                                                up vote
                                                1
                                                down vote










                                                up vote
                                                1
                                                down vote









                                                If you don't mind someone complaining about they don't understand your code, you could simply switch the order of the two conditionals:



                                                input="foo"
                                                VAR="1"

                                                if
                                                case $input in
                                                foo)
                                                [ $VAR = "1" ]
                                                ;;
                                                esac
                                                then
                                                echo "fallthrough worked!"
                                                fi


                                                Or:



                                                input="foo"
                                                VAR="1"

                                                case $input in
                                                foo)
                                                [ $VAR = "1" ]
                                                ;;
                                                esac &&
                                                echo "fallthrough worked!"


                                                Simple and clear (at least to me). case doesn't support fallthrough itself. But you can replace *) with && after esac to make it respect to the return values of other branches.






                                                share|improve this answer













                                                If you don't mind someone complaining about they don't understand your code, you could simply switch the order of the two conditionals:



                                                input="foo"
                                                VAR="1"

                                                if
                                                case $input in
                                                foo)
                                                [ $VAR = "1" ]
                                                ;;
                                                esac
                                                then
                                                echo "fallthrough worked!"
                                                fi


                                                Or:



                                                input="foo"
                                                VAR="1"

                                                case $input in
                                                foo)
                                                [ $VAR = "1" ]
                                                ;;
                                                esac &&
                                                echo "fallthrough worked!"


                                                Simple and clear (at least to me). case doesn't support fallthrough itself. But you can replace *) with && after esac to make it respect to the return values of other branches.







                                                share|improve this answer













                                                share|improve this answer



                                                share|improve this answer











                                                answered May 29 at 12:38









                                                user23013

                                                457210




                                                457210




















                                                    up vote
                                                    -4
                                                    down vote













                                                    New ;& and ;;& operators were introduced in Bash
                                                    4.0
                                                    and although they both might be useful in similar situations I think
                                                    they are of no use in your case. This is what man bash says about
                                                    these operators:




                                                    If the ;; operator is used, no subsequent matches are attempted after
                                                    the first pattern match. Using ;& in place of ;; causes execution to
                                                    continue with the list associated with the next set of patterns. Using
                                                    ;;& in place of ;; causes the shell to test the next pattern list in
                                                    the statement, if any, and execute any associated list on a successful
                                                    match.




                                                    In other words, ;& is a fall through and as we know it from C and
                                                    ;;& makes bash check remaining cases instead of returning from
                                                    case block entirely. You can find a nice example of ;;& in action
                                                    here: https://stackoverflow.com/a/24544780/3691891.



                                                    That being said, neither ;& nor ;;& could be used in your script
                                                    because both of them would go to *) that would be always run.



                                                    The following script works and does what you want without re-arranging
                                                    the logic but consider it only as an example and never rely on it, it's too fragile.
                                                    I've taken the idea from
                                                    here:



                                                    #!/usr/bin/env bash

                                                    function jumpto
                                                    grep -v ':$')
                                                    cmd=$(echo "$cmd"

                                                    input="foo"
                                                    VAR="1"

                                                    case $input in
                                                    foo)
                                                    if [ $VAR = "1" ]; then

                                                    printf "perform fallthroughn"
                                                    jumpto ft
                                                    else
                                                    printf "do not perform fallthroughn"

                                                    fi
                                                    ;;
                                                    *)
                                                    ft:
                                                    echo "fallthrough worked!"
                                                    ;;
                                                    esac





                                                    share|improve this answer





















                                                    • Why a downvote?
                                                      – Arkadiusz Drabczyk
                                                      May 28 at 20:15






                                                    • 1




                                                      This may work in a toy example but it's near-incomprehensible and wouldn't work in a larger script. The way you simulate goto is extremely fragile, and to say that it really simulates goto is an exaggeration. The code returns from the jumpto function and executes whatever comes after it. The fact that this is equivalent to continuing executing after the block between ft: and ;; is a coincidence because jumpto is the last command in the same complex command as the jumped-to block.
                                                      – Gilles
                                                      May 28 at 20:59






                                                    • 1




                                                      OK, I clearly emphasized that in my answer.
                                                      – Arkadiusz Drabczyk
                                                      May 28 at 21:01















                                                    up vote
                                                    -4
                                                    down vote













                                                    New ;& and ;;& operators were introduced in Bash
                                                    4.0
                                                    and although they both might be useful in similar situations I think
                                                    they are of no use in your case. This is what man bash says about
                                                    these operators:




                                                    If the ;; operator is used, no subsequent matches are attempted after
                                                    the first pattern match. Using ;& in place of ;; causes execution to
                                                    continue with the list associated with the next set of patterns. Using
                                                    ;;& in place of ;; causes the shell to test the next pattern list in
                                                    the statement, if any, and execute any associated list on a successful
                                                    match.




                                                    In other words, ;& is a fall through and as we know it from C and
                                                    ;;& makes bash check remaining cases instead of returning from
                                                    case block entirely. You can find a nice example of ;;& in action
                                                    here: https://stackoverflow.com/a/24544780/3691891.



                                                    That being said, neither ;& nor ;;& could be used in your script
                                                    because both of them would go to *) that would be always run.



                                                    The following script works and does what you want without re-arranging
                                                    the logic but consider it only as an example and never rely on it, it's too fragile.
                                                    I've taken the idea from
                                                    here:



                                                    #!/usr/bin/env bash

                                                    function jumpto
                                                    grep -v ':$')
                                                    cmd=$(echo "$cmd"

                                                    input="foo"
                                                    VAR="1"

                                                    case $input in
                                                    foo)
                                                    if [ $VAR = "1" ]; then

                                                    printf "perform fallthroughn"
                                                    jumpto ft
                                                    else
                                                    printf "do not perform fallthroughn"

                                                    fi
                                                    ;;
                                                    *)
                                                    ft:
                                                    echo "fallthrough worked!"
                                                    ;;
                                                    esac





                                                    share|improve this answer





















                                                    • Why a downvote?
                                                      – Arkadiusz Drabczyk
                                                      May 28 at 20:15






                                                    • 1




                                                      This may work in a toy example but it's near-incomprehensible and wouldn't work in a larger script. The way you simulate goto is extremely fragile, and to say that it really simulates goto is an exaggeration. The code returns from the jumpto function and executes whatever comes after it. The fact that this is equivalent to continuing executing after the block between ft: and ;; is a coincidence because jumpto is the last command in the same complex command as the jumped-to block.
                                                      – Gilles
                                                      May 28 at 20:59






                                                    • 1




                                                      OK, I clearly emphasized that in my answer.
                                                      – Arkadiusz Drabczyk
                                                      May 28 at 21:01













                                                    up vote
                                                    -4
                                                    down vote










                                                    up vote
                                                    -4
                                                    down vote









                                                    New ;& and ;;& operators were introduced in Bash
                                                    4.0
                                                    and although they both might be useful in similar situations I think
                                                    they are of no use in your case. This is what man bash says about
                                                    these operators:




                                                    If the ;; operator is used, no subsequent matches are attempted after
                                                    the first pattern match. Using ;& in place of ;; causes execution to
                                                    continue with the list associated with the next set of patterns. Using
                                                    ;;& in place of ;; causes the shell to test the next pattern list in
                                                    the statement, if any, and execute any associated list on a successful
                                                    match.




                                                    In other words, ;& is a fall through and as we know it from C and
                                                    ;;& makes bash check remaining cases instead of returning from
                                                    case block entirely. You can find a nice example of ;;& in action
                                                    here: https://stackoverflow.com/a/24544780/3691891.



                                                    That being said, neither ;& nor ;;& could be used in your script
                                                    because both of them would go to *) that would be always run.



                                                    The following script works and does what you want without re-arranging
                                                    the logic but consider it only as an example and never rely on it, it's too fragile.
                                                    I've taken the idea from
                                                    here:



                                                    #!/usr/bin/env bash

                                                    function jumpto
                                                    grep -v ':$')
                                                    cmd=$(echo "$cmd"

                                                    input="foo"
                                                    VAR="1"

                                                    case $input in
                                                    foo)
                                                    if [ $VAR = "1" ]; then

                                                    printf "perform fallthroughn"
                                                    jumpto ft
                                                    else
                                                    printf "do not perform fallthroughn"

                                                    fi
                                                    ;;
                                                    *)
                                                    ft:
                                                    echo "fallthrough worked!"
                                                    ;;
                                                    esac





                                                    share|improve this answer













                                                    New ;& and ;;& operators were introduced in Bash
                                                    4.0
                                                    and although they both might be useful in similar situations I think
                                                    they are of no use in your case. This is what man bash says about
                                                    these operators:




                                                    If the ;; operator is used, no subsequent matches are attempted after
                                                    the first pattern match. Using ;& in place of ;; causes execution to
                                                    continue with the list associated with the next set of patterns. Using
                                                    ;;& in place of ;; causes the shell to test the next pattern list in
                                                    the statement, if any, and execute any associated list on a successful
                                                    match.




                                                    In other words, ;& is a fall through and as we know it from C and
                                                    ;;& makes bash check remaining cases instead of returning from
                                                    case block entirely. You can find a nice example of ;;& in action
                                                    here: https://stackoverflow.com/a/24544780/3691891.



                                                    That being said, neither ;& nor ;;& could be used in your script
                                                    because both of them would go to *) that would be always run.



                                                    The following script works and does what you want without re-arranging
                                                    the logic but consider it only as an example and never rely on it, it's too fragile.
                                                    I've taken the idea from
                                                    here:



                                                    #!/usr/bin/env bash

                                                    function jumpto
                                                    grep -v ':$')
                                                    cmd=$(echo "$cmd"

                                                    input="foo"
                                                    VAR="1"

                                                    case $input in
                                                    foo)
                                                    if [ $VAR = "1" ]; then

                                                    printf "perform fallthroughn"
                                                    jumpto ft
                                                    else
                                                    printf "do not perform fallthroughn"

                                                    fi
                                                    ;;
                                                    *)
                                                    ft:
                                                    echo "fallthrough worked!"
                                                    ;;
                                                    esac






                                                    share|improve this answer













                                                    share|improve this answer



                                                    share|improve this answer











                                                    answered May 28 at 20:05









                                                    Arkadiusz Drabczyk

                                                    7,15521532




                                                    7,15521532











                                                    • Why a downvote?
                                                      – Arkadiusz Drabczyk
                                                      May 28 at 20:15






                                                    • 1




                                                      This may work in a toy example but it's near-incomprehensible and wouldn't work in a larger script. The way you simulate goto is extremely fragile, and to say that it really simulates goto is an exaggeration. The code returns from the jumpto function and executes whatever comes after it. The fact that this is equivalent to continuing executing after the block between ft: and ;; is a coincidence because jumpto is the last command in the same complex command as the jumped-to block.
                                                      – Gilles
                                                      May 28 at 20:59






                                                    • 1




                                                      OK, I clearly emphasized that in my answer.
                                                      – Arkadiusz Drabczyk
                                                      May 28 at 21:01

















                                                    • Why a downvote?
                                                      – Arkadiusz Drabczyk
                                                      May 28 at 20:15






                                                    • 1




                                                      This may work in a toy example but it's near-incomprehensible and wouldn't work in a larger script. The way you simulate goto is extremely fragile, and to say that it really simulates goto is an exaggeration. The code returns from the jumpto function and executes whatever comes after it. The fact that this is equivalent to continuing executing after the block between ft: and ;; is a coincidence because jumpto is the last command in the same complex command as the jumped-to block.
                                                      – Gilles
                                                      May 28 at 20:59






                                                    • 1




                                                      OK, I clearly emphasized that in my answer.
                                                      – Arkadiusz Drabczyk
                                                      May 28 at 21:01
















                                                    Why a downvote?
                                                    – Arkadiusz Drabczyk
                                                    May 28 at 20:15




                                                    Why a downvote?
                                                    – Arkadiusz Drabczyk
                                                    May 28 at 20:15




                                                    1




                                                    1




                                                    This may work in a toy example but it's near-incomprehensible and wouldn't work in a larger script. The way you simulate goto is extremely fragile, and to say that it really simulates goto is an exaggeration. The code returns from the jumpto function and executes whatever comes after it. The fact that this is equivalent to continuing executing after the block between ft: and ;; is a coincidence because jumpto is the last command in the same complex command as the jumped-to block.
                                                    – Gilles
                                                    May 28 at 20:59




                                                    This may work in a toy example but it's near-incomprehensible and wouldn't work in a larger script. The way you simulate goto is extremely fragile, and to say that it really simulates goto is an exaggeration. The code returns from the jumpto function and executes whatever comes after it. The fact that this is equivalent to continuing executing after the block between ft: and ;; is a coincidence because jumpto is the last command in the same complex command as the jumped-to block.
                                                    – Gilles
                                                    May 28 at 20:59




                                                    1




                                                    1




                                                    OK, I clearly emphasized that in my answer.
                                                    – Arkadiusz Drabczyk
                                                    May 28 at 21:01





                                                    OK, I clearly emphasized that in my answer.
                                                    – Arkadiusz Drabczyk
                                                    May 28 at 21:01













                                                     

                                                    draft saved


                                                    draft discarded


























                                                     


                                                    draft saved


                                                    draft discarded














                                                    StackExchange.ready(
                                                    function ()
                                                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f446537%2fcase-fallthrough-based-on-if-condition%23new-answer', 'question_page');

                                                    );

                                                    Post as a guest













































































                                                    Popular posts from this blog

                                                    How to check contact read email or not when send email to Individual?

                                                    Bahrain

                                                    Postfix configuration issue with fips on centos 7; mailgun relay