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}"
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
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 ‘}’.
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.
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.