BASH: OR operator for positional $1

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











up vote
0
down vote

favorite












I faced some issue, where OR operator doesn't work for $1.
Eg:



if [[ "$1" != '1' || '2' ]]
then
echo "BAD"
else
echo "OK"
fi


When I run this test no matter what $1 is, BAD always appears.



How can I tie $1 to be 1 or 2 only?







share|improve this question






















  • This is a very common error. I see it a lot with beginner programmers. However it is not how boolean logic works. Imagine putting in brackets. Where could you put them to make it work? Note there are some languages that you can ask if $1 is not in '1', '2' then … (see case example in bash).
    – ctrl-alt-delor
    Feb 8 at 12:47














up vote
0
down vote

favorite












I faced some issue, where OR operator doesn't work for $1.
Eg:



if [[ "$1" != '1' || '2' ]]
then
echo "BAD"
else
echo "OK"
fi


When I run this test no matter what $1 is, BAD always appears.



How can I tie $1 to be 1 or 2 only?







share|improve this question






















  • This is a very common error. I see it a lot with beginner programmers. However it is not how boolean logic works. Imagine putting in brackets. Where could you put them to make it work? Note there are some languages that you can ask if $1 is not in '1', '2' then … (see case example in bash).
    – ctrl-alt-delor
    Feb 8 at 12:47












up vote
0
down vote

favorite









up vote
0
down vote

favorite











I faced some issue, where OR operator doesn't work for $1.
Eg:



if [[ "$1" != '1' || '2' ]]
then
echo "BAD"
else
echo "OK"
fi


When I run this test no matter what $1 is, BAD always appears.



How can I tie $1 to be 1 or 2 only?







share|improve this question














I faced some issue, where OR operator doesn't work for $1.
Eg:



if [[ "$1" != '1' || '2' ]]
then
echo "BAD"
else
echo "OK"
fi


When I run this test no matter what $1 is, BAD always appears.



How can I tie $1 to be 1 or 2 only?









share|improve this question













share|improve this question




share|improve this question








edited Feb 8 at 11:55









Jeff Schaller

31.3k846105




31.3k846105










asked Feb 8 at 11:52









faceless

253




253











  • This is a very common error. I see it a lot with beginner programmers. However it is not how boolean logic works. Imagine putting in brackets. Where could you put them to make it work? Note there are some languages that you can ask if $1 is not in '1', '2' then … (see case example in bash).
    – ctrl-alt-delor
    Feb 8 at 12:47
















  • This is a very common error. I see it a lot with beginner programmers. However it is not how boolean logic works. Imagine putting in brackets. Where could you put them to make it work? Note there are some languages that you can ask if $1 is not in '1', '2' then … (see case example in bash).
    – ctrl-alt-delor
    Feb 8 at 12:47















This is a very common error. I see it a lot with beginner programmers. However it is not how boolean logic works. Imagine putting in brackets. Where could you put them to make it work? Note there are some languages that you can ask if $1 is not in '1', '2' then … (see case example in bash).
– ctrl-alt-delor
Feb 8 at 12:47




This is a very common error. I see it a lot with beginner programmers. However it is not how boolean logic works. Imagine putting in brackets. Where could you put them to make it work? Note there are some languages that you can ask if $1 is not in '1', '2' then … (see case example in bash).
– ctrl-alt-delor
Feb 8 at 12:47










4 Answers
4






active

oldest

votes

















up vote
5
down vote



accepted










With standard sh syntax (so not only recognised by bash but all other POSIX compatible shells):



case $1 in
(1 | 2) echo OK;;
(*) echo BAD;;
esac


Or:



if [ "$1" = 1 ] || [ "$1" = 2 ]; then
echo OK
else
echo BAD
fi


(note that it's a byte-to-byte comparison of strings. 01, 1e0, 1.0, 20/20, 0x1 would also be considered as BAD even though numerically they could be regarded as being the same as 1).



Note that the =/!= operators in bash's [[...]] construct (copied from ksh) are actually pattern matching operators as opposed to equality operators, so in this special case where you want to match a single character, you could also use [[ $1 != [12] ]] like you could do case $1 in ([12]) in standard sh syntax.






share|improve this answer






















  • Magnificent idea with case! Dunno how didn't i use it myself )
    – faceless
    Feb 8 at 12:42

















up vote
4
down vote













The reason you always go into the BAD branch of the if statement is that the test



[[ "$1" != '1' || '2' ]]


first tests whether $1 is not 1, and if it is not, BAD is printed. If it is, 2 is evaluated as a test. A string like 2 is always true, and BAD is printed.



Instead:



if [ "$1" != '1' ] && [ "$1" != '2' ]; then


or, with arithmetic tests,



if [ "$1" -ne 1 ] && [ "$1" -ne 2 ]; then


or, using arithmetic evaluation,



if (( $1 != 1 )) && (( $1 != 2 )); then





share|improve this answer





























    up vote
    1
    down vote













    if [[ "$1" != '1' || "$1" != '2' ]]
    then
    echo "BAD"
    else
    echo "OK"
    fi


    Then != statement needs to be repeated for the not equal to 2 as well as 1






    share|improve this answer




















    • The result is the same.
      – faceless
      Feb 8 at 11:59

















    up vote
    1
    down vote













    The logic of ($1 != 1) OR ($1 != 2) is flawed.



    If $1 is 1 then it is not equal to 2 so the test will be true.

    Also, if $1 is 2 then it is not equal to 1 so the test will be also true.
    In short, the test will always be true.



    You should test equality: ($1 == 1) or ($1 == 2) like this:



    if [[ ($1 == '1') || ($1 == '2') ]]; then
    echo "$1 OK"
    else
    echo "$1 BAD"
    fi


    Or simpler (in ksh, bash or zsh):



    [[ $1 == [12] ]] && echo "$1 OK" || echo "$1 BAD"


    Or using sh syntax (portable to all POSIX shells):



    if [ "$1" = '1' ] || [ "$1" = '2' ]; then
    echo "$1 OK"
    else
    echo "$1 BAD"
    fi


    Or with a case idiom:



    case $1 in
    (1 | 2) echo "$1 OK" ;;
    (*) echo BAD "$1 BAD" ;;
    esac


    All the above is a string comparison, if you want a numeric comparison, you may do:



    if [ "$1" -eq 1 ] || [ "$1" -eq 2 ]; then
    echo "$1 OK"
    else
    echo "$1 BAD"
    fi


    However, that will not work if $1 is 1.0 or 1e0 or many other numerical equivalent to 1. Will work with 01 or 0001 though.






    share|improve this answer


















    • 2




      Note that what is supported in [ "$1" -eq 1 ] varies from shell/[ to shell/[ (and is an arbitrary command injection in some if $1 comes from an untrusted source). With ksh93, that would return true for 1.0 or 1e0 or 20/20 and sometimes with RANDOM%2 and reboot with 'a[$(reboot)]'.
      – Stéphane Chazelas
      Feb 8 at 19:15











    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%2f422783%2fbash-or-operator-for-positional-1%23new-answer', 'question_page');

    );

    Post as a guest






























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    5
    down vote



    accepted










    With standard sh syntax (so not only recognised by bash but all other POSIX compatible shells):



    case $1 in
    (1 | 2) echo OK;;
    (*) echo BAD;;
    esac


    Or:



    if [ "$1" = 1 ] || [ "$1" = 2 ]; then
    echo OK
    else
    echo BAD
    fi


    (note that it's a byte-to-byte comparison of strings. 01, 1e0, 1.0, 20/20, 0x1 would also be considered as BAD even though numerically they could be regarded as being the same as 1).



    Note that the =/!= operators in bash's [[...]] construct (copied from ksh) are actually pattern matching operators as opposed to equality operators, so in this special case where you want to match a single character, you could also use [[ $1 != [12] ]] like you could do case $1 in ([12]) in standard sh syntax.






    share|improve this answer






















    • Magnificent idea with case! Dunno how didn't i use it myself )
      – faceless
      Feb 8 at 12:42














    up vote
    5
    down vote



    accepted










    With standard sh syntax (so not only recognised by bash but all other POSIX compatible shells):



    case $1 in
    (1 | 2) echo OK;;
    (*) echo BAD;;
    esac


    Or:



    if [ "$1" = 1 ] || [ "$1" = 2 ]; then
    echo OK
    else
    echo BAD
    fi


    (note that it's a byte-to-byte comparison of strings. 01, 1e0, 1.0, 20/20, 0x1 would also be considered as BAD even though numerically they could be regarded as being the same as 1).



    Note that the =/!= operators in bash's [[...]] construct (copied from ksh) are actually pattern matching operators as opposed to equality operators, so in this special case where you want to match a single character, you could also use [[ $1 != [12] ]] like you could do case $1 in ([12]) in standard sh syntax.






    share|improve this answer






















    • Magnificent idea with case! Dunno how didn't i use it myself )
      – faceless
      Feb 8 at 12:42












    up vote
    5
    down vote



    accepted







    up vote
    5
    down vote



    accepted






    With standard sh syntax (so not only recognised by bash but all other POSIX compatible shells):



    case $1 in
    (1 | 2) echo OK;;
    (*) echo BAD;;
    esac


    Or:



    if [ "$1" = 1 ] || [ "$1" = 2 ]; then
    echo OK
    else
    echo BAD
    fi


    (note that it's a byte-to-byte comparison of strings. 01, 1e0, 1.0, 20/20, 0x1 would also be considered as BAD even though numerically they could be regarded as being the same as 1).



    Note that the =/!= operators in bash's [[...]] construct (copied from ksh) are actually pattern matching operators as opposed to equality operators, so in this special case where you want to match a single character, you could also use [[ $1 != [12] ]] like you could do case $1 in ([12]) in standard sh syntax.






    share|improve this answer














    With standard sh syntax (so not only recognised by bash but all other POSIX compatible shells):



    case $1 in
    (1 | 2) echo OK;;
    (*) echo BAD;;
    esac


    Or:



    if [ "$1" = 1 ] || [ "$1" = 2 ]; then
    echo OK
    else
    echo BAD
    fi


    (note that it's a byte-to-byte comparison of strings. 01, 1e0, 1.0, 20/20, 0x1 would also be considered as BAD even though numerically they could be regarded as being the same as 1).



    Note that the =/!= operators in bash's [[...]] construct (copied from ksh) are actually pattern matching operators as opposed to equality operators, so in this special case where you want to match a single character, you could also use [[ $1 != [12] ]] like you could do case $1 in ([12]) in standard sh syntax.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 8 at 12:56

























    answered Feb 8 at 12:12









    Stéphane Chazelas

    281k53516847




    281k53516847











    • Magnificent idea with case! Dunno how didn't i use it myself )
      – faceless
      Feb 8 at 12:42
















    • Magnificent idea with case! Dunno how didn't i use it myself )
      – faceless
      Feb 8 at 12:42















    Magnificent idea with case! Dunno how didn't i use it myself )
    – faceless
    Feb 8 at 12:42




    Magnificent idea with case! Dunno how didn't i use it myself )
    – faceless
    Feb 8 at 12:42












    up vote
    4
    down vote













    The reason you always go into the BAD branch of the if statement is that the test



    [[ "$1" != '1' || '2' ]]


    first tests whether $1 is not 1, and if it is not, BAD is printed. If it is, 2 is evaluated as a test. A string like 2 is always true, and BAD is printed.



    Instead:



    if [ "$1" != '1' ] && [ "$1" != '2' ]; then


    or, with arithmetic tests,



    if [ "$1" -ne 1 ] && [ "$1" -ne 2 ]; then


    or, using arithmetic evaluation,



    if (( $1 != 1 )) && (( $1 != 2 )); then





    share|improve this answer


























      up vote
      4
      down vote













      The reason you always go into the BAD branch of the if statement is that the test



      [[ "$1" != '1' || '2' ]]


      first tests whether $1 is not 1, and if it is not, BAD is printed. If it is, 2 is evaluated as a test. A string like 2 is always true, and BAD is printed.



      Instead:



      if [ "$1" != '1' ] && [ "$1" != '2' ]; then


      or, with arithmetic tests,



      if [ "$1" -ne 1 ] && [ "$1" -ne 2 ]; then


      or, using arithmetic evaluation,



      if (( $1 != 1 )) && (( $1 != 2 )); then





      share|improve this answer
























        up vote
        4
        down vote










        up vote
        4
        down vote









        The reason you always go into the BAD branch of the if statement is that the test



        [[ "$1" != '1' || '2' ]]


        first tests whether $1 is not 1, and if it is not, BAD is printed. If it is, 2 is evaluated as a test. A string like 2 is always true, and BAD is printed.



        Instead:



        if [ "$1" != '1' ] && [ "$1" != '2' ]; then


        or, with arithmetic tests,



        if [ "$1" -ne 1 ] && [ "$1" -ne 2 ]; then


        or, using arithmetic evaluation,



        if (( $1 != 1 )) && (( $1 != 2 )); then





        share|improve this answer














        The reason you always go into the BAD branch of the if statement is that the test



        [[ "$1" != '1' || '2' ]]


        first tests whether $1 is not 1, and if it is not, BAD is printed. If it is, 2 is evaluated as a test. A string like 2 is always true, and BAD is printed.



        Instead:



        if [ "$1" != '1' ] && [ "$1" != '2' ]; then


        or, with arithmetic tests,



        if [ "$1" -ne 1 ] && [ "$1" -ne 2 ]; then


        or, using arithmetic evaluation,



        if (( $1 != 1 )) && (( $1 != 2 )); then






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Feb 8 at 12:41

























        answered Feb 8 at 12:02









        Kusalananda

        103k13202318




        103k13202318




















            up vote
            1
            down vote













            if [[ "$1" != '1' || "$1" != '2' ]]
            then
            echo "BAD"
            else
            echo "OK"
            fi


            Then != statement needs to be repeated for the not equal to 2 as well as 1






            share|improve this answer




















            • The result is the same.
              – faceless
              Feb 8 at 11:59














            up vote
            1
            down vote













            if [[ "$1" != '1' || "$1" != '2' ]]
            then
            echo "BAD"
            else
            echo "OK"
            fi


            Then != statement needs to be repeated for the not equal to 2 as well as 1






            share|improve this answer




















            • The result is the same.
              – faceless
              Feb 8 at 11:59












            up vote
            1
            down vote










            up vote
            1
            down vote









            if [[ "$1" != '1' || "$1" != '2' ]]
            then
            echo "BAD"
            else
            echo "OK"
            fi


            Then != statement needs to be repeated for the not equal to 2 as well as 1






            share|improve this answer












            if [[ "$1" != '1' || "$1" != '2' ]]
            then
            echo "BAD"
            else
            echo "OK"
            fi


            Then != statement needs to be repeated for the not equal to 2 as well as 1







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Feb 8 at 11:56









            Raman Sailopal

            1,18117




            1,18117











            • The result is the same.
              – faceless
              Feb 8 at 11:59
















            • The result is the same.
              – faceless
              Feb 8 at 11:59















            The result is the same.
            – faceless
            Feb 8 at 11:59




            The result is the same.
            – faceless
            Feb 8 at 11:59










            up vote
            1
            down vote













            The logic of ($1 != 1) OR ($1 != 2) is flawed.



            If $1 is 1 then it is not equal to 2 so the test will be true.

            Also, if $1 is 2 then it is not equal to 1 so the test will be also true.
            In short, the test will always be true.



            You should test equality: ($1 == 1) or ($1 == 2) like this:



            if [[ ($1 == '1') || ($1 == '2') ]]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            Or simpler (in ksh, bash or zsh):



            [[ $1 == [12] ]] && echo "$1 OK" || echo "$1 BAD"


            Or using sh syntax (portable to all POSIX shells):



            if [ "$1" = '1' ] || [ "$1" = '2' ]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            Or with a case idiom:



            case $1 in
            (1 | 2) echo "$1 OK" ;;
            (*) echo BAD "$1 BAD" ;;
            esac


            All the above is a string comparison, if you want a numeric comparison, you may do:



            if [ "$1" -eq 1 ] || [ "$1" -eq 2 ]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            However, that will not work if $1 is 1.0 or 1e0 or many other numerical equivalent to 1. Will work with 01 or 0001 though.






            share|improve this answer


















            • 2




              Note that what is supported in [ "$1" -eq 1 ] varies from shell/[ to shell/[ (and is an arbitrary command injection in some if $1 comes from an untrusted source). With ksh93, that would return true for 1.0 or 1e0 or 20/20 and sometimes with RANDOM%2 and reboot with 'a[$(reboot)]'.
              – Stéphane Chazelas
              Feb 8 at 19:15















            up vote
            1
            down vote













            The logic of ($1 != 1) OR ($1 != 2) is flawed.



            If $1 is 1 then it is not equal to 2 so the test will be true.

            Also, if $1 is 2 then it is not equal to 1 so the test will be also true.
            In short, the test will always be true.



            You should test equality: ($1 == 1) or ($1 == 2) like this:



            if [[ ($1 == '1') || ($1 == '2') ]]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            Or simpler (in ksh, bash or zsh):



            [[ $1 == [12] ]] && echo "$1 OK" || echo "$1 BAD"


            Or using sh syntax (portable to all POSIX shells):



            if [ "$1" = '1' ] || [ "$1" = '2' ]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            Or with a case idiom:



            case $1 in
            (1 | 2) echo "$1 OK" ;;
            (*) echo BAD "$1 BAD" ;;
            esac


            All the above is a string comparison, if you want a numeric comparison, you may do:



            if [ "$1" -eq 1 ] || [ "$1" -eq 2 ]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            However, that will not work if $1 is 1.0 or 1e0 or many other numerical equivalent to 1. Will work with 01 or 0001 though.






            share|improve this answer


















            • 2




              Note that what is supported in [ "$1" -eq 1 ] varies from shell/[ to shell/[ (and is an arbitrary command injection in some if $1 comes from an untrusted source). With ksh93, that would return true for 1.0 or 1e0 or 20/20 and sometimes with RANDOM%2 and reboot with 'a[$(reboot)]'.
              – Stéphane Chazelas
              Feb 8 at 19:15













            up vote
            1
            down vote










            up vote
            1
            down vote









            The logic of ($1 != 1) OR ($1 != 2) is flawed.



            If $1 is 1 then it is not equal to 2 so the test will be true.

            Also, if $1 is 2 then it is not equal to 1 so the test will be also true.
            In short, the test will always be true.



            You should test equality: ($1 == 1) or ($1 == 2) like this:



            if [[ ($1 == '1') || ($1 == '2') ]]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            Or simpler (in ksh, bash or zsh):



            [[ $1 == [12] ]] && echo "$1 OK" || echo "$1 BAD"


            Or using sh syntax (portable to all POSIX shells):



            if [ "$1" = '1' ] || [ "$1" = '2' ]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            Or with a case idiom:



            case $1 in
            (1 | 2) echo "$1 OK" ;;
            (*) echo BAD "$1 BAD" ;;
            esac


            All the above is a string comparison, if you want a numeric comparison, you may do:



            if [ "$1" -eq 1 ] || [ "$1" -eq 2 ]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            However, that will not work if $1 is 1.0 or 1e0 or many other numerical equivalent to 1. Will work with 01 or 0001 though.






            share|improve this answer














            The logic of ($1 != 1) OR ($1 != 2) is flawed.



            If $1 is 1 then it is not equal to 2 so the test will be true.

            Also, if $1 is 2 then it is not equal to 1 so the test will be also true.
            In short, the test will always be true.



            You should test equality: ($1 == 1) or ($1 == 2) like this:



            if [[ ($1 == '1') || ($1 == '2') ]]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            Or simpler (in ksh, bash or zsh):



            [[ $1 == [12] ]] && echo "$1 OK" || echo "$1 BAD"


            Or using sh syntax (portable to all POSIX shells):



            if [ "$1" = '1' ] || [ "$1" = '2' ]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            Or with a case idiom:



            case $1 in
            (1 | 2) echo "$1 OK" ;;
            (*) echo BAD "$1 BAD" ;;
            esac


            All the above is a string comparison, if you want a numeric comparison, you may do:



            if [ "$1" -eq 1 ] || [ "$1" -eq 2 ]; then
            echo "$1 OK"
            else
            echo "$1 BAD"
            fi


            However, that will not work if $1 is 1.0 or 1e0 or many other numerical equivalent to 1. Will work with 01 or 0001 though.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Feb 8 at 19:11









            Stéphane Chazelas

            281k53516847




            281k53516847










            answered Feb 8 at 19:02









            Isaac

            6,6381734




            6,6381734







            • 2




              Note that what is supported in [ "$1" -eq 1 ] varies from shell/[ to shell/[ (and is an arbitrary command injection in some if $1 comes from an untrusted source). With ksh93, that would return true for 1.0 or 1e0 or 20/20 and sometimes with RANDOM%2 and reboot with 'a[$(reboot)]'.
              – Stéphane Chazelas
              Feb 8 at 19:15













            • 2




              Note that what is supported in [ "$1" -eq 1 ] varies from shell/[ to shell/[ (and is an arbitrary command injection in some if $1 comes from an untrusted source). With ksh93, that would return true for 1.0 or 1e0 or 20/20 and sometimes with RANDOM%2 and reboot with 'a[$(reboot)]'.
              – Stéphane Chazelas
              Feb 8 at 19:15








            2




            2




            Note that what is supported in [ "$1" -eq 1 ] varies from shell/[ to shell/[ (and is an arbitrary command injection in some if $1 comes from an untrusted source). With ksh93, that would return true for 1.0 or 1e0 or 20/20 and sometimes with RANDOM%2 and reboot with 'a[$(reboot)]'.
            – Stéphane Chazelas
            Feb 8 at 19:15





            Note that what is supported in [ "$1" -eq 1 ] varies from shell/[ to shell/[ (and is an arbitrary command injection in some if $1 comes from an untrusted source). With ksh93, that would return true for 1.0 or 1e0 or 20/20 and sometimes with RANDOM%2 and reboot with 'a[$(reboot)]'.
            – Stéphane Chazelas
            Feb 8 at 19:15













             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f422783%2fbash-or-operator-for-positional-1%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