Bash: let statement vs assignment
let
does exactly what (( ))
do, it is for arithmetic expressions. There is almost no difference between let
and (( ))
.
Your examples are invalid. var=${var}bar
is going to add word bar
to the var
variable (which is a string operation), let var+=bar
is not going to work, because it is not an arithmetic expression:
$ var='5'; let var+=bar; echo "$var"
5
Actually, it IS an arithmetic expression, if only variable bar
was set, otherwise bar
is treated as zero.
$ var='5'; bar=2; let var+=bar; echo "$var"
7
Bash assignment with let fails with /
let
is a shell builtin that is a another way to use the $((..))
Arithmetic Expansion in bash. The assignment
let var2=/tmp
is treated by the shell as an arithmetic operation "division" with an incorrect quotient value. It is equivalent to doing.
var=$((/tmp))
Since there are incorrect number of operands, the parser has thrown the error that you are seeing. Note that tmp
is still treated in a variable context by the shell. If the parser had identified the expression as valid, then tmp
would have undergone variable expansion. Since it is not set before, it would have likely thrown a "division-by-zero" error.
For simple variable assignments just drop the let
keyword and enclose the value field within "quotes"
var2="/tmp"
bash: assignment AND condition test in nested statement?
Is this compact form generally possible in bash
No, it is not, at least not without a custom code to handle it. Command substitution is run in a subshell - changes will not be visible in parent shell. Arithmetic expansion does only arithmetic operations - all strings are converted to numbers (as if by atoi()/strtol()
), if no digits are scanned they are converted to 0.
The usual way is just to assign the variable with a &&
followed by test - that allows to check the exit status of the command and grab the result.
if ! {
bus_connection="$(lsblk -dn -o TRAN /dev/sdd)" &&
test "$bus_connection" = "usb"
}; then
echo "not usb"
exit 1
fi
or just ignore the exit status of lsblk
:
if
bus_connection="$(lsblk -dn -o TRAN /dev/sdd)"
! test "$bus_connection" = "usb"
then
echo "not usb"
exit 1
fi
Still you could write your own function that uses bash namereference to assign the first argument to the second and return with test
s exit status:
test_and_assign() {
declare -n _test_and_assign_ref=$1
shift
_test_and_assign_ref="$1"
test "$@"
}
$ test_and_assign bus_connection "$(echo 123)" = "usb"
$ echo "$? $bus_connection"
1 123
$ test_and_assign bus_connection "$(echo usb)" = "usb"
$ echo "$? $bus_connection"
0 usb
Note that here, as in your first code snippet with local bus_connection=$(...)
, the exit status of the command substitution is ignored.
Variable assignment in command substitution
Here's man bash
:
SIMPLE COMMAND EXPANSION
When a simple command is executed, the shell performs the fol‐
lowing expansions, assignments, and redirections, from left to
right.
1. The words that the parser has marked as variable
assignments (those preceding the command name) and
redirections are saved for later processing.
2. The words that are not variable assignments or redirec‐
tions are expanded. If any words remain after expan‐
sion, the first word is taken to be the name of the
command and the remaining words are the arguments.
[...]
In your case, the simple command has a single word $(echo var=foo)
.
Since there are no words marked as variable assignments (because this word is instead a command substitution), step 1 doesn't apply.
We then move on to step 2, where the word $(echo var=foo)
is expanded into var=foo
. We don't go back to the first step, we just do what step 2 says: "take the first word as the name of the command".
This is why var=foo
is executed as a command instead of being interpreted as an assignment.
Shell Script : shortcut add and assignment += : command not found
Your syntax for incrementing the variable is correct, but you are using it in a context where Bash wants a command, and it complains that the result of the increment (4
) is not a recognized command.
The let
keyword is your friend.
let SumVar+=4
Or better yet just leave out the dollar sign (thanks @chepner);
(( SumVar += 4 ))
How to build a conditional assignment in bash?
As per Jonathan's comment:
variable=$(( 1 == 1 ? 1 : 0 ))
EDIT:
I revised the original answer which just echo
'd the value of the condition operator, it didn't actually show any assignment.
Related Topics
Selecting Text in Terminal Without Using the Mouse
Postgresql Won't Start: "Server.Key" Has Group or World Access
What Is Start-Stop-Daemon in Linux Scripting
How to Know If I'm Running a Nested Shell
Mongodb Service Not Running in Fedora
What Is the Linux Process Table? What Does It Consist Of
Using Bash Script to Find Line Number of String in File
Examining Berkeley Db Files from the Cli
How to Use Aliased Commands with Xargs
How to Mount from Command Line Like the Nautilus Does
Create a Static Haskell Linux Executable
Remove Only Files in Directory on Linux Not Directories
Equivalent of Ctrl C in Command to Cancel a Program
Does the Thundering Herd Problem Exist on Linux Anymore
How to Change(Hide) the Nginx Server Signature
How to Not Transfer Changes Done to Files from a Branch to a Another in Git