difference between $[a-b] and $((a-b)) in bash [duplicate] - bash

This question already has answers here:
bash: $[<arithmetic-expression>] vs. $((<arithmetic-expression>))
(2 answers)
Closed 6 years ago.
I don’t know this operator $[] and couldn’t find something about it. However I know that next two codes give the same output
a=4
b=1
echo $[a-b] # => 3
and
a=4
b=1
echo $((a-b)) # => 3
So what is $[] operator for, and what’s the difference with $(()) ?
In my zsh shell prompt, when I open any of them and no close them, I have mathsubst written.

Reading man bash says that the old format $[expression] is deprecated and will be removed. Otherwise they should be equivalent.
Arithmetic expansion allows the evaluation of an arithmetic expression
and the substitution of the result. The format for arithmetic
expansion is:
$((expression))
The old format $[expression] is deprecated and will be removed in
upcoming versions of bash.

Related

Syntax error using expr to get string length [duplicate]

This question already has answers here:
How to store the length of a string in a variable in bash?
(2 answers)
Closed 4 years ago.
On mac running 4.4.23(1), an example I've seen used for finding the length of a string throws an error:
string_var=blah
echo `expr length $string_var`
expr: syntax error
Works fine on my Debian system.
shopt options are: himvBHs
expr is not part of bash -- it's an ancient UNIX tool from back when the shell couldn't do math (or much else useful) on its own.
You don't need it. In the modern day, ${#var} will give you the length of the value assigned to var, as follows:
string_var=blah
echo "${#string_var}"

Why Pycharm gives warning on "simple variable usage" in .sh bash script? [duplicate]

This question already has answers here:
When do we need curly braces around shell variables?
(7 answers)
Closed 6 years ago.
In Pycharm when we use variable e.g. $privateKey, we get the warning Simple variable usage as below snapshot and recommend us to turn to the syntax ${privateKey}
My question is why we get such warning? What is the risk to use simple variable like that?
When clicking more
Thanks to #Whymarrh. One answer is as below.
since "$foobar" would instead expand foobar
My answer is to separate/distinguish $myVar and notInVar in string "$myVarnotInVar"
In other words
myVar=122
echo "$myVarnotInVar" # will print empty string "" since undefined variable $myVarnotInVar
echo "${myVar}notInVar" # will print 122notInVar

Why does bash brace expansion work in some arithmetic expressions but not others?

I am working on a very simple bash script and I'm having a problem with understating why deprecated $[] is working flawlessly, while $(()) seems to break the whole thing.
The code I'm referring to is:
for i in {1..10};
do
printf %4d $[{1..10}*i]
echo
done
In this version I am having no issues, yet I wouldn't like to use deprecated bash elements, that's why I wanted to switch to $(()).
Unfortunately, as soon as I change my code to:
printf %4d $(({1..10}*i))
I receive an error:
./script_bash.sh: line 8: {1..10}*i: syntax error: argument expected (error token is "{1..10}*i")
I'd be thankful for some help with this one...
Setting the way back machine for 1990.
Bash implemented the $[] syntax per POSIX P1003.2d9 (circa 1990), which was a draft of the released P1003.2-1992. In the two years between draft and standard, POSIX had instead settled on the ksh88 $(()) syntax and behaviors. Chet Ramey (bash maintainer) had this to say, back in 2012:
Bash... implemented $[...] because there was no other
syntax at the time, and to gain some operational experience with
arithmetic expansion in the shell. Bash-1.14... lists both forms of arithmetic expansion, but by
the time bash-2.0 was released in 1995, the manual referred only to
the $((...)) form.
This suggests to me that the $[] form was experimental, and it had certain behaviors (like brace expansion) that were specified into oblivion when POSIX adopted the $(()) syntax. Those experimental behaviors were left in, since there were already scripts in the wild relying on them (remember more than 2 years had elapsed).
Chet makes clear in that same thread that the $[] form is obsolete, but not deprecated:
Now, it's hardly any problem to keep dragging the $[...] syntax along.
It takes only a few dozen bytes of code. I have no plans to remove it.
The current POSIX standard, C.2.6 Word Expansions > Arithmetic Expansion mentions the syntax (emphasis mine):
In early proposals, a form $[expression] was used. It was functionally equivalent to the "$(())" of the current text, but objections were lodged that the 1988 KornShell had already implemented "$(())" and there was no compelling reason to invent yet another syntax. Furthermore, the "$[]" syntax had a minor incompatibility involving the patterns in case statements.
So the as-implemented behavior in bash isn't quite to specification, but since there are no plans to remove it, I see no reason to forgo its benefits if it neatly solves your problem. However, as pointed out by #Barmar's comment, it'd be A Good Idea to comment the code and link it here so future developers know what the heck you mean!
$(()) is for arithmetic expressions, and brace expansion isn't done in arithmetic.
Make an array with a loop:
for i in {1..10}
do
vals=()
for j in {1..10}
do
vals+=($((i*j)))
done
printf "%4d" ${vals[#]}
done
printf %4d $(({1..10}*i))
does not work because of the order in which parameters are expanded in bash. The brace expansion ({}) is done earlier than arithmetic expansion ($(())) by bash. Your code would definitely work if it were other way around.
From man bash:
The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion.
Ran across some bash like this. This question asks for explanation, rather than solution, but here would be a $(())-way of expressing this.
for i in {1..10}; do
printf %4d $(eval echo '$(('{1..10}'*i))')
echo
done
Brace expansion is inhibited inside an arithmetic expansion like it is for parameter expansion.
(bash manual)
To avoid conflicts with parameter expansion, the string ‘${’ is not
considered eligible for brace expansion, and inhibits brace expansion
until the closing ‘}’.

how to combine multi bash parameter expansion [duplicate]

This question already has answers here:
Can ${var} parameter expansion expressions be nested in bash?
(15 answers)
Closed 5 years ago.
bash parameter expansion has a few useful function, e.g. substring ,replace,upper,lower. how to combine these function without define temporary parameter?
f="abc.txt"
e=${f:4:3} #txt
echo ${e^^} #TXT
I define e to upper the txt. echo ${${f:4:3}^^} can not work. Is it possible omit e. if in java i can write
String f="abc.txt";
System.out.print(f.substring(4,7).toUpperCase());
even, i can
System.out.print("abc.txt".substring(4,7).toUpperCase());
No, this is not possible in bash AFAIK.
To make it possible we would need some sort of prioritization (along-with parsing logic changes) when more than 1 parameter expansion is specified, for which there is no code as of now.

why we use ##*/ expression with bash variable [duplicate]

This question already has answers here:
explain the linux regex for getting filename
(2 answers)
Closed 8 years ago.
I am tring to understand the bash script.
I am seeing ##* / expression with bash variable.
i.e ${foo##*/}
Can someone please tell me why we use that expression?
It's called "Parameter expansion". The variable $foo is searched for a substring matching the pattern */ (i.e. anything up to a slash) from the beginning (#), and what remains in the variable is returned. Doubling the #-sign makes the matching greedy, i.e. it tries to find the longest possible match.

Resources