Boost up with bash scripts
Specify shell for your script
Your shell script can be executed by different shells, to explicitly specify the shell executable, leave a comment with format !{absolute_shell_path}
.
#!/bin/bash
Variable
Declare a variable
In shell scripts, we declare a variable without any keyword. And the value a variable can have no punctuation for strings, they are strings by default. If contains spaces, use double quote to delimitate it, or the John
in this context will be recognized as a command.
FIRST_NAME=John
LAST_NAME=Smith
FULL_NAME="John Smith"
2
3
Referencing a variable
Since strings have no punctuations, we use double quote to prevent globbing and word splitting when referencing it. echo
accepts variadic parameters so they are concatenated naturally.
echo My full name is: $FIRST_NAME $LAST_NAME
echo Hello "$FULL_NAME"
2
INFO
The best practice for referencing a string variable is always punctuate with double quote.
Assigning variable inline
Unlike some programming languages, shell script invokes a function or executable at the begin of a command and may assign the value to variable after the invoked.
echo "What's your first name?"
read -r FIRST_NAME
echo "What's your last name?"
read -r LAST_NAME
echo Hello "$FIRST_NAME $LAST_NAME"
2
3
4
5
6
INFO
-r
option stands for raw string.
Positional arguments
We can specify positional arguments for values we'd like to pass when invoking our shell script.
# in test.sh
echo Hello "$1" "$2"
2
INFO
It's also a good practice to brace place holder symbol with double quote.
Call this script with values.
./test.sh John Smith
# Hello John Smith
2
3
Control flows
Test operator
Test operator (or test expression) is the core role of control flow statements. There are three ways to write a test operator:
TIP
- Use
$
to retrieve value returned by statement or command. [ ... ]
and[[ ... ]]
should have one space for both side of[
and]
.
condition=$(test "$1" -gt "$2")
condition=$([ "$1" -gt "$2" ])
condition=$([[ $1 > $2 ]])
However, using [[ ... ]]
id much preferred because it offers more natural syntax for use.
Pattern Matching:
- Supports advanced pattern matching with the
==
operator.
- Supports advanced pattern matching with the
Extended Logical Operators:
- Allows the use of logical operators (
&&
and||
) for combining multiple conditions.
- Allows the use of logical operators (
Regular Expressions:
- Supports the
=~
operator for regular expression matching.
- Supports the
Extended String Comparison:
- Provides additional string comparison operators (
<
,>
,<=
, etc.).
- Provides additional string comparison operators (
Logical Negation:
- Supports the
!
operator for logical negation.
- Supports the
Variable Expansion:
- Variables don't need to be quoted in most cases for improved readability.
Improved Quoting:
- Less sensitive to quoting issues, making it more forgiving.
Using [[ ... ]]
is recommended when advanced conditional expressions are needed in Bash scripting.
if
, then
, elif
, else
and fi
if [[ $1 > 70 ]]; then
echo "You might be too old to drive..."
elif [[ $1 < 16 ]]; then
echo "You are too young to drive!"
else
echo "Let's go get your license."
fi
2
3
4
5
6
7
INFO
- Every condition expression should be terminated by semicolon
;
. fi
is the reverse ofif
. 😅
case
in
case-in
statement is rather advanced switch
like control flow statement, it offers some pattern matching feature, way better than the old stupid switch
in c lang.
case $1 in
"apple" | "banana")
echo "This is fruit."
;;
"car")
echo "This is a vehicle."
;;
*)
echo "I don't know what it is."
;;
esac
2
3
4
5
6
7
8
9
10
11
switch (item)
{
case "apple" or "banana":
Console.WriteLine("This is fruit.");
break;
case "car":
Console.WriteLine("This is a vehicle.");
break;
default:
Console.WriteLine("I don't know what it is.");
break;
}
2
3
4
5
6
7
8
9
10
11
12
INFO
esac
is the reverse of case
.😅
Array
Init an array
arr=(1 2 3 4 5)
Access array element
first=${arr[0]}
WARNING
Access array element using ${arr[idx]}
instead of $(arr[idx])
.
for
in
arr=(1 2 3 4 5)
for item in "${arr[@]}"; do
echo "$item"
done
2
3
4
5
INFO
"${arr[@]}"
references an whole iterable array instead of first element.
while
, do
and done
while [[ ]]
Function
user="Jane"
get_user() {
local user="$1" # scoped, Jane will not be overridden.
local age="$2"
echo "Current user is $user, $age years old.";
}
get_user "John" "18" # invoke the function only after the definition.
2
3
4
5
6
7
INFO
- Use
local
keyword to declare a function scope only variable. - Set positional parameters by order instead of a parameter list.
- Positional parameter are
local
by default.
- Positional parameter are
- Function only available after definition.