Operators and related topics
Operator
assignment
Assigning, initializing, or modifying the value of a variable
=
A general assignment operator that can be used for arithmetic and string assignments.
var=12 car=bmw # Cannot have a blank character after the = sign
Don't confuse = assignment operator with = test operator
# =Here is the test operator if [ "$string1" = "$string2" ] # If ["X$string1" = "X$string2"] is a safer practice, # This prevents errors when one of the two variables is empty. # (The character "X" as a prefix can cancel each other on either side of the equation.) then command fi
arithmetic operator
+
Addition calculation
-
Subtraction calculation
*
Multiplication calculation
/
Division calculation
**
exponentiation
# In Bash, version 2.02, the'**'power operator was introduced. let "z=5**3" echo "z = $z" # z = 125
%
Modular operation, or complementary operation
greatest common factor
#!/bin/bash # gcd.sh: Maximum common divisor #Algorithms using Euclid # The "greatest common divisor" (gcd) of two integers, #+is the maximum number that two integers can divide at the same time. # The Euclid algorithm uses continuous division. # In each cycle, #+Divided<--Divided #+Division<--Remainder #+until the remainder= 0. #+In the last loop, gcd = dividend. # # A better discussion of the Euclid algorithm can be found at #+ Jim Loy's site, http://www.jimloy.com/number/euclids.htm. # ------------------------------------------------------ # Parameter Check ARGS=2 E_BADARGS=65 if [ $# -ne "$ARGS" ] then echo "Usage: `basename $0` first-number second-number" exit $E_BADARGS fi # ------------------------------------------------------ gcd () { dividend=$1 # Assignment at will. divisor=$2 #+Here, it doesn't matter which value is given. # Why is that okay? remainder=1 # If an uninitialized variable is used in the loop, #+Then in the first loop, #+It will produce an error message. until [ "$remainder" -eq 0 ] do let "remainder = $dividend % $divisor" dividend=$divisor # Now repeat with the two smallest numbers. divisor=$remainder done # Algorithms for Euclid } # Last $dividend is the gcd. gcd $1 $2 echo; echo "GCD of $1 and $2 = $dividend"; echo # Exercise : # -------- # Check the command line parameters passed in to make sure they are all integers. #+If it's not an integer, give an appropriate error message and exit the script. exit 0
results of enforcement
andrew@andrew:/work/bash/src$ bash gcd.sh 2345 56 GCD of 2345 and 56 = 7
+=
"Add-Equal" (add a constant to the value of the variable and assign the result to the variable) let "var += 5" The value of the VaR variable will be added 5 to the original value.
-=
"Minus-equal" (subtracts the value of a variable from a constant and assigns the result to the variable)
*=
Multiply-Equal (multiplies the value of a variable by a constant value, and assigns the result to a variable)
Let "var *= 4" The result of the VaR variable will be multiplied by 4.
/=
Divide-Equal (divides the value of a variable by a constant value, and assigns the result to the variable)
%=
Modulo-Equal (modulo a variable by dividing it by a constant and assigning the result to a variable)
Arithmetic operators often appear in expr or let expressions.
Using Arithmetic Operators
#!/bin/bash # Use 10 different methods to count to 11. n=1; echo -n "$n " let "n = $n + 1" # let "n = n + 1" also works. echo -n "$n " : $((n = $n + 1)) # ":" is necessary because if there is no ":", then #+ Bash will try to interpret'$((n = $n + 1))'as a command. echo -n "$n " (( n = n + 1 )) # The above sentence is a simpler way. # Thank you, David Lombard, for pointing this out. echo -n "$n " n=$(($n + 1)) echo -n "$n " : $[ n = $n + 1 ] # ":" is necessary because if there is no ":", then #+ Bash will try to interpret'$[n = $n + 1]'as a command. # This sentence works even if "n" is initialized as a string. echo -n "$n " n=$[ $n + 1 ] # This sentence works even if "n" is initialized as a string. #*This type of structure should be avoided as much as possible because it is obsolete and not portable. echo -n "$n " # No final carriage return when echo output # Now let's do a C-style incremental operation. let "n++" # Let'++ n'is also possible. echo -n "$n " (( n++ )) # (++n) is also possible. echo -n "$n " : $(( n++ )) # : $((++n)) is also possible. echo -n "$n " : $[ n++ ] # : $[++n]] is also possible. echo -n "$n " echo exit 0
results of enforcement
andrew@andrew:/work/bash/src$ bash algroth.sh 1 2 3 4 5 6 7 8 9 10 11
An integer variable in bash is actually a signed long(32-bit) integer value that ranges from -2147483648 to 2147483647.If you do arithmetic beyond this range, you will not get the results you expect.
You can't do floating-point calculations directly in bash. If you need floating-point calculations, you need to use bc in your script. This command can do floating-point calculations or call Mathematical Library functions.
Bitwise operators
<<
Move one bit to the left
<<=
"Move left-assign"
let "var <<= 2"
The result of this sentence is that the variable var is moved 2 bits to the left (that is, multiplied by 4)
>>
Move one bit to the right
>>=
Right Shift-Assignment
&
Bitwise and
&=
"Bitwise and-Assignment"
|
Bitwise or
|=
"Bitwise or-Assignment"
~
Bitwise Reverse
!
Bitwise Not
^
Bitwise XOR
^=
"Bitwise XOR-Assignment"
Logical Operator
&&
And (logical)
if [ $condition1 ] && [ $condition2 ] # Same as if [$condition1-a $condition2] # If both condition1 and condition2 are true, the result is true. if [[ $condition1 && $condition2 ]] #It's fine too ## Note &&Symbols are not allowed in [...]
||
Or (logical)
if [ $condition1 ] || [ $condition2 ] # Same as if [$condition1 -o $condition2] # If one of condition1 or condition2 is true, the result is true. if [[ $condition1 || $condition2 ]] # It's fine too. # Note that the || operator cannot appear in the [...] structure.
Mixed Conditional Test Using &&and||
#!/bin/bash a=24 b=47 # The condition holds if a==24 and b==47 if [ "$a" -eq 24 ] && [ "$b" -eq 47 ] then echo "Test #1 succeeds." else echo "Test #1 fails." fi # ERROR: Not in single brackets &&but in double brackets if [ "$a" -eq 24 && "$b" -eq 47 ] #+Try running'['$a'-eq 24' #+Failed because no matching']'was found. # # Note: if [[$a-eq 24 & & & &$b-eq 24]] also works. # if-test structure with double middle brackets is better than #+Single middle bracket if-test structure is more flexible. #(Line 17'&'has a different meaning from line 6'&'.) if [ "$a" -eq 98 ] || [ "$b" -eq 47 ] then echo "Test #2 succeeds." else echo "Test #2 fails." fi # The -a and -o options are provided #+An optional mixed-condition test method. if [ "$a" -eq 24 -a "$b" -eq 47 ] then echo "Test #3 succeeds." else echo "Test #3 fails." fi if [ "$a" -eq 98 -o "$b" -eq 47 ] then echo "Test #4 succeeds." else echo "Test #4 fails." fi a=rhino b=crocodile if [ "$a" = rhino ] && [ "$b" = crocodile ] then echo "Test #5 succeeds." else echo "Test #5 fails." fi exit 0
Detecting the script using the shellcheck tool
andrew@andrew:/work/bash/src$ shellcheck if_else.sh In if_else.sh line 15: if [ "$a" -eq 24 && "$b" -eq 47 ] ^-- SC1073: Couldn't parse this if expression. In if_else.sh line 57: exit 0 ^-- SC1050: Expected 'then'. ^-- SC1072: Expected 'then'.. Fix any mentioned problems and try again.
Prompt the script for a problem on line 15. Look at line 15 of the script to see that
If ['$a'-eq 24 & & & &'$b'-eq 47] script uses &" in single brackets
The &&and || operators can also be used in arithmetic contexts.
andrew@andrew:~$ echo $(( 1 && 2 )) $((3 && 0)) $((4 || 0)) $((0 || 0)) 1 0 1 0
,
, sign operator, comma operator can link two or more arithmetic operations, all operations will be run, but only the result of the last operation will be returned
let "t1 = ((5 + 3, 7 - 1, 15 - 4))" echo "t1 = $t1" # t1 = 11 let "t2 = ((a = 9, 15 / 3))" # Set "a" and calculate "t2". echo "t2 = $t2 a = $a"# t2 = 5 a = 9
numeric constants
By default, shell scripts treat numbers as decimal, unless they are marked or prefixed with a special tag.If a number starts with 0, it is 8-digit; if a number starts with 0x, it is 16-digit; if # is embedded in the middle of the number, it is considered a BASE#NUMBER notation.
Numeric Constant Representation
#!/bin/bash # Number.sh: Several different numeric representations. # 10-digit: default let "dec = 32" echo "decimal number = $dec" # 32 # It's nothing special. # Octal: Begins with'0'(zero) # Octal 32 happens to be 3*8 + 2 = 26 let "oct = 032" echo "octal number = $oct" # 26 # The result of the expression is expressed in decimal. # --------------------------- # Hexadecimal: Numbers starting with'0x'or'0X' # Hexadecimal 0x32 is 60 let "hex = 0x32" echo "hexadecimal number = $hex" # 50 # The result of the expression is expressed in decimal. # Other Binary: BASE#NUMBER # BASE ranges from 2 to 64. # NUMBER values must be represented by symbols in the BASE range, as shown in the following example. # Binary let "bin = 2#111100111001101" echo "binary number = $bin" # 31181 let "b32 = 32#77" echo "base-32 number = $b32" # 231 let "b64 = 64#@_" echo "base-64 number = $b64" # 4031 # This representation can only work within a limited ASCII character range (2 - 64). # 10 digits + 26 lowercase letters + 26 uppercase characters + @ + _ echo echo $((36#zz)) $((2#10101010)) $((16#AF16)) $((53#1aA)) # 1295 170 44822 3375 # Important considerations: # --------------- # Using a number that exceeds the given number, #+will cause an error. let "bad_oct = 081" # (partial) error message output: # bad_oct = 081: value too great for base (error token is "081") #Octal numbers use only digits in the range 0 - 7. exit 0
andrew@andrew:/work/bash/src$ andrew@andrew:/work/bash/src$ shellcheck numbers.sh andrew@andrew:/work/bash/src$ bash numbers.sh decimal number = 32 octal number = 26 hexadecimal number = 50 binary number = 31181 base-32 number = 231 base-64 number = 4031 1295 170 44822 3375 numbers.sh: Line 56: let: bad_oct = 081: Numeric value too large to be base of arithmetic digit (The error symbol is "081")