03. Variables and Expressions (Part 2)
Expressions
An expression is a series of operators and operands that evaluate to a single resulting value
The operator is a symbol that represent a specific task the computer will do
The operand is the data that the operator works on
Example: In the expression n1 + n2
n1 and n2 are the operands, + is the operator, and the expression will evaluate to a single number as a result
There are 3 types of expressions
Arithmetic: do calculation
Conditional: compare values and evaluate to true or false
File test: determine file status
Arithmetic Expressionse
For integers only
Operators:
+ add
– subtract
* multiply
/ divide (remember that it’s integer division, so you’ll get an integer as a result. For example: 3 / 2 => 1 as a result)
% modulus (calculates the remainder of a division. For example: 5 / 3 => 1 5 % 3 => 2)
++ Pre-increment (value in variable is incremented by 1 first, then use in any other evaluation)
Example: ++n * 3 means that n is incremented first, then the new n value is multiplied by 3
++ Post-increment (value in variable used in any necessary evaluation, then the value in the variable is incremented last)
Example: n++ * 3 means that the original n value is multiplied by 3 first, then n is incremented
– – [2 minus sign next to each other] Pre-decrement (value in variable is decremented by 1 first, then use in any other evaluation)
Example: --n * 3 means that n is decremented first, then the new n value is multiplied by 3
– – [2 minus sign next to each other] Post-decrement (value in variable n is used in any necessary evaluation first, then n is decremented by 1)
Example: n-- * 3 means that the original n value is multiplied by 3 first, then n is decremented
= assignment (store data value on the right side into variable on the left side)
*= multiply and assign (example: n *= 3 means n = n * 3)
/= divide and assign (example: n /= 3 means n = n / 3)
%= modulus and assign (example: n %= 3 means n = n % 3)
+= add and assign (example: n += 3 means n = n + 3)
-= subtract and assign (example: n -= 3 means n = n - 3)
Operands can be:
variables, as long as they store integer values
constants
There are 2 ways to evaluate an arithmetic expressions:
let and (( ))
If you don’t use one of the 2 ways above, the arithmetic evaluation will not be performed.
For example: var=5+2 means that var will store the string “5+2”, not the number 7
When evaluating arithmetic expression, order of operation is the same as in math: ( ) has highest precedence, then multiply and divide and modulus in order from left to right, then add and subtract in order from left to right, and assignment has the lowest precedence
Arithmetic Evaluation with let
Format: let “outputVar = expression”
outputVar is the variable that stores the result of the evaluation
expression is any arithmetic expression
there is no $ in front of any variable name
the double quotes are required if you use space or ( ) in the expression
Example:
let “output1 = 5 + 2” use quotes due to space
echo $output 1 print 7
let output2=6*3/2 no space or ( ), no quotes needed
echo $output 2 print 9
let “output3=6*(3/2)” use quotes due to ( )
echo $output3 print 6
Note that the order of operation is the same as in math, which explains the difference in output2 and output3
Arithmetic Evaluation with (( ))
Format: ((outputVar = expression))
outputVar is the variable that stores the result of the evaluation
expression is any arithmetic expression
there is no $ in front of any variable name
Example:
(( output1 = 5 + 2 )) space is ok
echo $output 1 print 7
((output2=6*3/2)) no space is ok
echo $output 2 print 9
(( output3=6*(3/2) )) note order of operation due to ( )
echo $output3 print 6
Note that the order of operation is the same as in math, which explains the difference in output2 and output3
Between the 2 formats to evaluate arithmetic expressions, (( )) is more common
Conditional Expressions
Conditional expressions are evaluated to true or false, and are used for looping and selection statements
The shell variable ? stores the exit status of a command that has just finished running
Therefore, after a conditional expression you can use: echo $? to see if the expression evaluates to true or false
When an expression evaluates to true, the ? variable is 0 When an expression evaluates to false, the ? variable is 1
This is because an exit status of 0 is considered success in Linux / Unix
Conditional expressions are divided into:
Relational expression to compare integers
Relational expressions to compare strings
Logical expressions: to group multiple logical conditions together
Relational Expression for Integers
There are 3 ways to evaluate integer relational expressions
First way: using (( )) just like with arithmetic expressions
Operators:
< less than
> greater than
<= less than or equal to
>= greater than or equal to
== equal to
!= not equal to
Format: (( operand1 operator operand2))
operand1 and operand2 can be a variable or a constant
there is no $ in front of the variable name
Example:
n=5
(( n <= 5 )) n <= 5 is true
echo $? ? is 0
Second way: use [[ ]]
Operators:
-lt less than
-gt greater than
-le less than or equal to
-ge greater than or equal to
-eq equal to
-ne not equal to
Format: [[ operand1 operator operand2 ]]
operand1 and operand2 can be a variable or a constant
there must be a space after [[ and a space before ]]
Example:
n=5
[[ n -lt 5 ]] n -lt 5 is false
echo $? ? is 1
Third way: use [ ]
Operators are the same as with [[ ]]
-lt less than
-gt greater than
-le less than or equal to
-ge greater than or equal to
-eq equal to
-ne not equal to
Format : [ operand1 operator operand2 ]
operand1 and operand2 can be a variable or a constant
there must be $ in front of a variable name
there must be a space after [ and a space before ]
Example:
n=5
[ $n -ge 5 ] n -ge 5 is true
echo $? ? is 0
Relational Expression for Strings
There are 2 ways to evaluate string relational expressions
First way: use [ ]
Operators:
= or == equal to (matching)
!= not equal to (not matching)
\< less than (comes before, based on ascii order)
\> greater than (comes after, based on ascii order)
-z zero length or empty string
All string compares are ASCII compare of character by character
Format 1: [ operand1 operator operand2 ]
operand1 and operand2 can be a variable or a constant
there must be $ in front of the variable name and it’s safer to have double quotes around the variable name
there must be a space after [ and a space before ]
Example:
n=“/home/student”
[ $n != ~ ] n not equal home dir is true
echo $? ? is 0
Second way: use [[ ]]
Operators:
= or == equal to (matching)
!= not equal to (not matching)
< less than (comes before, based on ascii order)
> greater than (comes after, based on ascii order)
-z zero length or empty string
=~ matching a string with regular expression
Format 1: [[ operand1 operator operand2 ]]
operand1 and operand2 can be a variable or a constant
there must be $ in front of the variable name
there must be a space after [[ and a space before ]]
Example:
n=“/home/student”
[[ -z $n ]] n is empty string will evaluate to false
echo $? ? is 1
Between the 2 formats to evaluate string relational expression, [[ ]] is the most often used due to the operators that it takes
For a thorough discussion between [ ] and [[ ]], see this link: https://mywiki.wooledge.org/BashFAQ/031
Logical Expressions
Logical expressions are used to evaluate conditions that are T or F
Operators
! logical not: reverses true to false, and false to true
Example: if n is 2, then [[ ! $n –gt 0 ]] is false
and [ ! $n –gt 0 ] is false
and (( ! n > 0 )) is false
&& and -a
logical and: true only if both left and right sides are true, otherwise false if at least one side is false
T&&T => T T&&F => F F&&T => F F&&F => F
T –a T => T T –a F => F F –a T => F F –a F => F
&& is used with (( )) and [[ ]]
-a is used with [ ]
Example: if n is 2, m is 4, then (( m > n && n < 0 )) is false
and [[ $m –gt $n && $n -lt 0 ]] is false
and [ $m –gt $n -a $n -lt 0 ] is false
|| and -o
logical or: false only if both left and right sides are false, otherwise true if at least one side is true
T || T => T T || F => T F || T => T F || F => F
T –o T => T T –o F => T F –o T => T F –o F => F
|| is used with (( )) and [[ ]]
-o is used with [ ]
Example: if n is 2, m is 4, then (( m > n || n < 0 )) is true
and [[ $m –gt $n || $n -lt 0 ]] is true
and [ $m –gt $n -o $n -lt 0 ] is true
File Test Expressions
For evaluating file status
Operators
-e exists
-f is a regular file
-d is a directory
-h is a symbolic link
-s has a non-zero size (not empty)
-r has read permission
-w has write permission
-x has execute permission
-nt is newer than
-ot is older than
-ef is hard linked with
Operands can be:
Variables that contain a filename
String constants that are filenames
To evaluate file test expressions, use [ ] or [[ ]]
there is no difference
Examples using both formats
If fA is a symbolic link and is older than fB
[ -e fA ] evaluates to T
[[ -f fA ]] F
[ -d fA ] F
[[ -h fA ]] T
[ -s fA ] T
[[ -r fA ]] T
[ -w fA ] T
[[ -x fA ]] T
[ fA –nt fB ] F
[[ fA –ot fB ]] T
[[ fA –ef fB ]] F