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

Clash 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?
linux bash
add a comment |Â
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?
linux bash
the whitespace around the '*' caused it to be evaluated differently
â guiverc
Dec 26 '17 at 0:54
add a comment |Â
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?
linux bash
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?
linux bash
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
add a comment |Â
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
add a comment |Â
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
add a comment |Â
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
add a comment |Â
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:
as a wild card in file name glob
multiply
0 or more times in regex
...
and how bash parse commands (greatly simplified, it's very complicated actually):
parameter substitution
command substitution
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ï¼Â
add a comment |Â
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
add a comment |Â
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
add a comment |Â
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
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
edited Dec 26 '17 at 3:27
muru
33.5k577144
33.5k577144
answered Dec 26 '17 at 1:41
Isaac
6,7911834
6,7911834
add a comment |Â
add a comment |Â
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
add a comment |Â
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
add a comment |Â
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
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
answered Dec 26 '17 at 4:34
bu5hman
1,164214
1,164214
add a comment |Â
add a comment |Â
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:
as a wild card in file name glob
multiply
0 or more times in regex
...
and how bash parse commands (greatly simplified, it's very complicated actually):
parameter substitution
command substitution
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ï¼Â
add a comment |Â
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:
as a wild card in file name glob
multiply
0 or more times in regex
...
and how bash parse commands (greatly simplified, it's very complicated actually):
parameter substitution
command substitution
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ï¼Â
add a comment |Â
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:
as a wild card in file name glob
multiply
0 or more times in regex
...
and how bash parse commands (greatly simplified, it's very complicated actually):
parameter substitution
command substitution
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ï¼Â
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:
as a wild card in file name glob
multiply
0 or more times in regex
...
and how bash parse commands (greatly simplified, it's very complicated actually):
parameter substitution
command substitution
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ï¼Â
edited Dec 26 '17 at 2:05
answered Dec 26 '17 at 1:40
frams
374217
374217
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
the whitespace around the '*' caused it to be evaluated differently
â guiverc
Dec 26 '17 at 0:54