Why the asterisk (*) wildcard is not evaluated in these two cases?

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











up vote
0
down vote

favorite












If I have this command:



expr 2 * 4


It will not work, because the * wildcard will be evaluated, and so I have to escape it:



expr 2 * 4



But if I have the following two cases:



let var1=2*4

var2=$((2*4))


Then the * wildcard will not be evaluated, and so there is no need to escape it.



Why the * wildcard did not get evaluated in the above two cases? my guess is that bash simply does not evaluate it when using let and $(()).



If this is the case, are there other situations where wildcards do not get evaluated?







share|improve this question




















  • the whitespace around the '*' caused it to be evaluated differently
    – guiverc
    Dec 26 '17 at 0:54














up vote
0
down vote

favorite












If I have this command:



expr 2 * 4


It will not work, because the * wildcard will be evaluated, and so I have to escape it:



expr 2 * 4



But if I have the following two cases:



let var1=2*4

var2=$((2*4))


Then the * wildcard will not be evaluated, and so there is no need to escape it.



Why the * wildcard did not get evaluated in the above two cases? my guess is that bash simply does not evaluate it when using let and $(()).



If this is the case, are there other situations where wildcards do not get evaluated?







share|improve this question




















  • the whitespace around the '*' caused it to be evaluated differently
    – guiverc
    Dec 26 '17 at 0:54












up vote
0
down vote

favorite









up vote
0
down vote

favorite











If I have this command:



expr 2 * 4


It will not work, because the * wildcard will be evaluated, and so I have to escape it:



expr 2 * 4



But if I have the following two cases:



let var1=2*4

var2=$((2*4))


Then the * wildcard will not be evaluated, and so there is no need to escape it.



Why the * wildcard did not get evaluated in the above two cases? my guess is that bash simply does not evaluate it when using let and $(()).



If this is the case, are there other situations where wildcards do not get evaluated?







share|improve this question












If I have this command:



expr 2 * 4


It will not work, because the * wildcard will be evaluated, and so I have to escape it:



expr 2 * 4



But if I have the following two cases:



let var1=2*4

var2=$((2*4))


Then the * wildcard will not be evaluated, and so there is no need to escape it.



Why the * wildcard did not get evaluated in the above two cases? my guess is that bash simply does not evaluate it when using let and $(()).



If this is the case, are there other situations where wildcards do not get evaluated?









share|improve this question











share|improve this question




share|improve this question










asked Dec 26 '17 at 0:42









user267498

1




1











  • the whitespace around the '*' caused it to be evaluated differently
    – guiverc
    Dec 26 '17 at 0:54
















  • the whitespace around the '*' caused it to be evaluated differently
    – guiverc
    Dec 26 '17 at 0:54















the whitespace around the '*' caused it to be evaluated differently
– guiverc
Dec 26 '17 at 0:54




the whitespace around the '*' caused it to be evaluated differently
– guiverc
Dec 26 '17 at 0:54










3 Answers
3






active

oldest

votes

















up vote
1
down vote













In var2=2*4, because of spaces (metacharacters), and that there is no file starting with a 2, some characters, and a 4 in the pwd.



The line is split in tokens using spaces as delimiters.



This has no spaces (and after the = it is considered quoted):



$ var1=2*4


But this does:



$ echo 2 * 4 


And the * becomes a token and is expanded (as a filename expansion).



To avoid the special effect of * use quoting:



$ expr 2 * 4
8
$ expr 2 "*" 4
8
$ expr 2 '*' 4
8


However, this does expand:



$ touch 2good4
$ echo 2*4
2good4


In echo $((2*4)), what is inside a $((…)) construct is interpreted as an arithmetic expansion. any of this will do the same (even with the spaces):



$ echo $((2*4))
8
$ echo $(( 2 * 4 ))
8
$ echo $(( 2 * 4 ))
8





share|improve this answer





























    up vote
    1
    down vote













    The behaviour you see is explained here for globbing and here for expansion and the man let page for the parameter specification bash knows to give to 'let'



    When bash sees * on it's own it performs pathname expansion except
    where the expansion returns a null result in which case it returns the literal string.



    echo 2 * 4 #echo 2, the contents of the pwd and then 4


    If * is preceded by a marker that tells it to use a difference form or expansion (math/command/parameter or no expansion at all) then it uses the relevant method. So



    let var1=2*4 #pass the **arithmetic** argument var1=2*4 to the let command because bash knows let takes special characters (% * etc) as arguments

    var2=$((2*4)) #bash parses the string as far as $ and sees an instruction to expand
    #bash then sees (( the which specifies arithmetic expansion specifies


    and as you said



    echo 2 * 4 #perform no expansion





    share|improve this answer



























      up vote
      0
      down vote













      If you want to know the reason, you should know what can * do in bash and how bash parse commands:



      first, what can * do in bash:



      1. as a wild card in file name glob


      2. multiply



      3. 0 or more times in regex



        ...



      and how bash parse commands (greatly simplified, it's very complicated actually):



      1. parameter substitution


      2. command substitution



      3. globbing



        ...



      Suppose you hava a.txt b.txt in current directory, in expr 2 * 4, after parameter substitution -> command substitution
      -> globbing, it will become



      expr 2 a.txt b.txt 4


      which of cause will not return the right answer.



      However in expr 2 * 4, * is a character! None of parameter substitution, command substitution, globbing will affect it. so expr get 3 parameters 2 * 4, and it will return 8.



      In let var1=2*4, bash make an arithmetic substitution before globing, the command after pasing is let var1=8. If you have 2a4 2b4 in current directory and you dont't use let, just



      var1=2*4
      echo $var1


      It will return 2a4 2b4, NOT 8.



      In var2=$((2*4)), bash make an arithmetic substitution too because (()) is arithmetic operator.



      PS: If you want * be an arithmetic operator, keep it in (()) $ or using let,eg:



      ((var1 = 2 * 4)) or var1=$((2 * 4))
      var1=$[2 * 4]


      WHITESPACES are allowed!






      share|improve this answer






















        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%2f413041%2fwhy-the-asterisk-wildcard-is-not-evaluated-in-these-two-cases%23new-answer', 'question_page');

        );

        Post as a guest






























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes








        up vote
        1
        down vote













        In var2=2*4, because of spaces (metacharacters), and that there is no file starting with a 2, some characters, and a 4 in the pwd.



        The line is split in tokens using spaces as delimiters.



        This has no spaces (and after the = it is considered quoted):



        $ var1=2*4


        But this does:



        $ echo 2 * 4 


        And the * becomes a token and is expanded (as a filename expansion).



        To avoid the special effect of * use quoting:



        $ expr 2 * 4
        8
        $ expr 2 "*" 4
        8
        $ expr 2 '*' 4
        8


        However, this does expand:



        $ touch 2good4
        $ echo 2*4
        2good4


        In echo $((2*4)), what is inside a $((…)) construct is interpreted as an arithmetic expansion. any of this will do the same (even with the spaces):



        $ echo $((2*4))
        8
        $ echo $(( 2 * 4 ))
        8
        $ echo $(( 2 * 4 ))
        8





        share|improve this answer


























          up vote
          1
          down vote













          In var2=2*4, because of spaces (metacharacters), and that there is no file starting with a 2, some characters, and a 4 in the pwd.



          The line is split in tokens using spaces as delimiters.



          This has no spaces (and after the = it is considered quoted):



          $ var1=2*4


          But this does:



          $ echo 2 * 4 


          And the * becomes a token and is expanded (as a filename expansion).



          To avoid the special effect of * use quoting:



          $ expr 2 * 4
          8
          $ expr 2 "*" 4
          8
          $ expr 2 '*' 4
          8


          However, this does expand:



          $ touch 2good4
          $ echo 2*4
          2good4


          In echo $((2*4)), what is inside a $((…)) construct is interpreted as an arithmetic expansion. any of this will do the same (even with the spaces):



          $ echo $((2*4))
          8
          $ echo $(( 2 * 4 ))
          8
          $ echo $(( 2 * 4 ))
          8





          share|improve this answer
























            up vote
            1
            down vote










            up vote
            1
            down vote









            In var2=2*4, because of spaces (metacharacters), and that there is no file starting with a 2, some characters, and a 4 in the pwd.



            The line is split in tokens using spaces as delimiters.



            This has no spaces (and after the = it is considered quoted):



            $ var1=2*4


            But this does:



            $ echo 2 * 4 


            And the * becomes a token and is expanded (as a filename expansion).



            To avoid the special effect of * use quoting:



            $ expr 2 * 4
            8
            $ expr 2 "*" 4
            8
            $ expr 2 '*' 4
            8


            However, this does expand:



            $ touch 2good4
            $ echo 2*4
            2good4


            In echo $((2*4)), what is inside a $((…)) construct is interpreted as an arithmetic expansion. any of this will do the same (even with the spaces):



            $ echo $((2*4))
            8
            $ echo $(( 2 * 4 ))
            8
            $ echo $(( 2 * 4 ))
            8





            share|improve this answer














            In var2=2*4, because of spaces (metacharacters), and that there is no file starting with a 2, some characters, and a 4 in the pwd.



            The line is split in tokens using spaces as delimiters.



            This has no spaces (and after the = it is considered quoted):



            $ var1=2*4


            But this does:



            $ echo 2 * 4 


            And the * becomes a token and is expanded (as a filename expansion).



            To avoid the special effect of * use quoting:



            $ expr 2 * 4
            8
            $ expr 2 "*" 4
            8
            $ expr 2 '*' 4
            8


            However, this does expand:



            $ touch 2good4
            $ echo 2*4
            2good4


            In echo $((2*4)), what is inside a $((…)) construct is interpreted as an arithmetic expansion. any of this will do the same (even with the spaces):



            $ echo $((2*4))
            8
            $ echo $(( 2 * 4 ))
            8
            $ echo $(( 2 * 4 ))
            8






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 26 '17 at 3:27









            muru

            33.5k577144




            33.5k577144










            answered Dec 26 '17 at 1:41









            Isaac

            6,7911834




            6,7911834






















                up vote
                1
                down vote













                The behaviour you see is explained here for globbing and here for expansion and the man let page for the parameter specification bash knows to give to 'let'



                When bash sees * on it's own it performs pathname expansion except
                where the expansion returns a null result in which case it returns the literal string.



                echo 2 * 4 #echo 2, the contents of the pwd and then 4


                If * is preceded by a marker that tells it to use a difference form or expansion (math/command/parameter or no expansion at all) then it uses the relevant method. So



                let var1=2*4 #pass the **arithmetic** argument var1=2*4 to the let command because bash knows let takes special characters (% * etc) as arguments

                var2=$((2*4)) #bash parses the string as far as $ and sees an instruction to expand
                #bash then sees (( the which specifies arithmetic expansion specifies


                and as you said



                echo 2 * 4 #perform no expansion





                share|improve this answer
























                  up vote
                  1
                  down vote













                  The behaviour you see is explained here for globbing and here for expansion and the man let page for the parameter specification bash knows to give to 'let'



                  When bash sees * on it's own it performs pathname expansion except
                  where the expansion returns a null result in which case it returns the literal string.



                  echo 2 * 4 #echo 2, the contents of the pwd and then 4


                  If * is preceded by a marker that tells it to use a difference form or expansion (math/command/parameter or no expansion at all) then it uses the relevant method. So



                  let var1=2*4 #pass the **arithmetic** argument var1=2*4 to the let command because bash knows let takes special characters (% * etc) as arguments

                  var2=$((2*4)) #bash parses the string as far as $ and sees an instruction to expand
                  #bash then sees (( the which specifies arithmetic expansion specifies


                  and as you said



                  echo 2 * 4 #perform no expansion





                  share|improve this answer






















                    up vote
                    1
                    down vote










                    up vote
                    1
                    down vote









                    The behaviour you see is explained here for globbing and here for expansion and the man let page for the parameter specification bash knows to give to 'let'



                    When bash sees * on it's own it performs pathname expansion except
                    where the expansion returns a null result in which case it returns the literal string.



                    echo 2 * 4 #echo 2, the contents of the pwd and then 4


                    If * is preceded by a marker that tells it to use a difference form or expansion (math/command/parameter or no expansion at all) then it uses the relevant method. So



                    let var1=2*4 #pass the **arithmetic** argument var1=2*4 to the let command because bash knows let takes special characters (% * etc) as arguments

                    var2=$((2*4)) #bash parses the string as far as $ and sees an instruction to expand
                    #bash then sees (( the which specifies arithmetic expansion specifies


                    and as you said



                    echo 2 * 4 #perform no expansion





                    share|improve this answer












                    The behaviour you see is explained here for globbing and here for expansion and the man let page for the parameter specification bash knows to give to 'let'



                    When bash sees * on it's own it performs pathname expansion except
                    where the expansion returns a null result in which case it returns the literal string.



                    echo 2 * 4 #echo 2, the contents of the pwd and then 4


                    If * is preceded by a marker that tells it to use a difference form or expansion (math/command/parameter or no expansion at all) then it uses the relevant method. So



                    let var1=2*4 #pass the **arithmetic** argument var1=2*4 to the let command because bash knows let takes special characters (% * etc) as arguments

                    var2=$((2*4)) #bash parses the string as far as $ and sees an instruction to expand
                    #bash then sees (( the which specifies arithmetic expansion specifies


                    and as you said



                    echo 2 * 4 #perform no expansion






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Dec 26 '17 at 4:34









                    bu5hman

                    1,164214




                    1,164214




















                        up vote
                        0
                        down vote













                        If you want to know the reason, you should know what can * do in bash and how bash parse commands:



                        first, what can * do in bash:



                        1. as a wild card in file name glob


                        2. multiply



                        3. 0 or more times in regex



                          ...



                        and how bash parse commands (greatly simplified, it's very complicated actually):



                        1. parameter substitution


                        2. command substitution



                        3. globbing



                          ...



                        Suppose you hava a.txt b.txt in current directory, in expr 2 * 4, after parameter substitution -> command substitution
                        -> globbing, it will become



                        expr 2 a.txt b.txt 4


                        which of cause will not return the right answer.



                        However in expr 2 * 4, * is a character! None of parameter substitution, command substitution, globbing will affect it. so expr get 3 parameters 2 * 4, and it will return 8.



                        In let var1=2*4, bash make an arithmetic substitution before globing, the command after pasing is let var1=8. If you have 2a4 2b4 in current directory and you dont't use let, just



                        var1=2*4
                        echo $var1


                        It will return 2a4 2b4, NOT 8.



                        In var2=$((2*4)), bash make an arithmetic substitution too because (()) is arithmetic operator.



                        PS: If you want * be an arithmetic operator, keep it in (()) $ or using let,eg:



                        ((var1 = 2 * 4)) or var1=$((2 * 4))
                        var1=$[2 * 4]


                        WHITESPACES are allowed!






                        share|improve this answer


























                          up vote
                          0
                          down vote













                          If you want to know the reason, you should know what can * do in bash and how bash parse commands:



                          first, what can * do in bash:



                          1. as a wild card in file name glob


                          2. multiply



                          3. 0 or more times in regex



                            ...



                          and how bash parse commands (greatly simplified, it's very complicated actually):



                          1. parameter substitution


                          2. command substitution



                          3. globbing



                            ...



                          Suppose you hava a.txt b.txt in current directory, in expr 2 * 4, after parameter substitution -> command substitution
                          -> globbing, it will become



                          expr 2 a.txt b.txt 4


                          which of cause will not return the right answer.



                          However in expr 2 * 4, * is a character! None of parameter substitution, command substitution, globbing will affect it. so expr get 3 parameters 2 * 4, and it will return 8.



                          In let var1=2*4, bash make an arithmetic substitution before globing, the command after pasing is let var1=8. If you have 2a4 2b4 in current directory and you dont't use let, just



                          var1=2*4
                          echo $var1


                          It will return 2a4 2b4, NOT 8.



                          In var2=$((2*4)), bash make an arithmetic substitution too because (()) is arithmetic operator.



                          PS: If you want * be an arithmetic operator, keep it in (()) $ or using let,eg:



                          ((var1 = 2 * 4)) or var1=$((2 * 4))
                          var1=$[2 * 4]


                          WHITESPACES are allowed!






                          share|improve this answer
























                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            If you want to know the reason, you should know what can * do in bash and how bash parse commands:



                            first, what can * do in bash:



                            1. as a wild card in file name glob


                            2. multiply



                            3. 0 or more times in regex



                              ...



                            and how bash parse commands (greatly simplified, it's very complicated actually):



                            1. parameter substitution


                            2. command substitution



                            3. globbing



                              ...



                            Suppose you hava a.txt b.txt in current directory, in expr 2 * 4, after parameter substitution -> command substitution
                            -> globbing, it will become



                            expr 2 a.txt b.txt 4


                            which of cause will not return the right answer.



                            However in expr 2 * 4, * is a character! None of parameter substitution, command substitution, globbing will affect it. so expr get 3 parameters 2 * 4, and it will return 8.



                            In let var1=2*4, bash make an arithmetic substitution before globing, the command after pasing is let var1=8. If you have 2a4 2b4 in current directory and you dont't use let, just



                            var1=2*4
                            echo $var1


                            It will return 2a4 2b4, NOT 8.



                            In var2=$((2*4)), bash make an arithmetic substitution too because (()) is arithmetic operator.



                            PS: If you want * be an arithmetic operator, keep it in (()) $ or using let,eg:



                            ((var1 = 2 * 4)) or var1=$((2 * 4))
                            var1=$[2 * 4]


                            WHITESPACES are allowed!






                            share|improve this answer














                            If you want to know the reason, you should know what can * do in bash and how bash parse commands:



                            first, what can * do in bash:



                            1. as a wild card in file name glob


                            2. multiply



                            3. 0 or more times in regex



                              ...



                            and how bash parse commands (greatly simplified, it's very complicated actually):



                            1. parameter substitution


                            2. command substitution



                            3. globbing



                              ...



                            Suppose you hava a.txt b.txt in current directory, in expr 2 * 4, after parameter substitution -> command substitution
                            -> globbing, it will become



                            expr 2 a.txt b.txt 4


                            which of cause will not return the right answer.



                            However in expr 2 * 4, * is a character! None of parameter substitution, command substitution, globbing will affect it. so expr get 3 parameters 2 * 4, and it will return 8.



                            In let var1=2*4, bash make an arithmetic substitution before globing, the command after pasing is let var1=8. If you have 2a4 2b4 in current directory and you dont't use let, just



                            var1=2*4
                            echo $var1


                            It will return 2a4 2b4, NOT 8.



                            In var2=$((2*4)), bash make an arithmetic substitution too because (()) is arithmetic operator.



                            PS: If you want * be an arithmetic operator, keep it in (()) $ or using let,eg:



                            ((var1 = 2 * 4)) or var1=$((2 * 4))
                            var1=$[2 * 4]


                            WHITESPACES are allowed!







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Dec 26 '17 at 2:05

























                            answered Dec 26 '17 at 1:40









                            frams

                            374217




                            374217






















                                 

                                draft saved


                                draft discarded


























                                 


                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f413041%2fwhy-the-asterisk-wildcard-is-not-evaluated-in-these-two-cases%23new-answer', 'question_page');

                                );

                                Post as a guest













































































                                Popular posts from this blog

                                Peggy Mitchell

                                Palaiologos

                                The Forum (Inglewood, California)