Because bash is the standard default shell interpreter for Linux, it can be said that bash is the foundation of shell programming.
This article focuses on bash syntax, not Linux directives.
: Notebook: This article has been archived to: “blog” : Keyboard: The source code for this article has been archived to linux-tutorial
█ █ █ █ █ █ █ ╗ █ █ ╗ █ █ ╗ █ █ █ █ █ █ █ ╗ █ █ ╗ █ █ ╗ █ █ ╔ ═ ═ ═ ═ ╝ █ █ ║ █ █ ║ █ █ ╔ ═ ═ ═ ═ ╝ █ █ ║ █ █ ║ █ █ █ █ █ █ █ ╗ █ █ █ █ █ █ █ ║ █ █ █ █ █ ╗ █ █ ║ █ █ ║ ╚ ═ ═ ═ ═ █ █ ║ █ █ ╔ ═ ═ █ █ ║ █ █ ╔ ═ ═ ╝ █ █ ║ █ █ ║ █ █ █ █ █ █ █ ║ █ █ ║ █ █ ║ █ █ █ █ █ █ █ ╗ █ █ █ █ █ █ █ ╗ █ █ █ █ █ █ █ ╗Copy the code
1. Introduction
1.1. What is a shell
- Shell is a program written in C language, which is the bridge for users to use Linux.
- Shell is both a command language and a programming language.
- A Shell is an application that provides an interface through which users can access the services of the Linux kernel.
Ken Thompson’s SH was the first Unix Shell, and Windows Explorer is a typical graphical interface Shell.
1.2. What is a shell script
A Shell script is a script program written for a Shell. The file suffix is.sh.
The industry usually refers to shell script, but shell and shell script are two different concepts.
1.3. The Shell environment
Shell programming, like Java and PHP programming, requires only a text editor that can write the code and a script interpreter that can interpret the execution.
There are many types of Shell interpreters. The common ones are:
- Sh – Bourne Shell. Sh is the standard default SHELL for Unix.
- Bash – Bourne Again Shell. Bash is the standard default Shell for Linux.
- Fish – Intelligent and user friendly command line shell.
- Xiki – makes the shell console friendlier and more powerful.
- ZSH – powerful shell and scripting language.
Specifies the script interpreter
In shell scripts, #! Tell the system that the program specified in the following path is the Shell interpreter that interprets the script file. #! It’s called a shebang (also known as a Hashbang).
So, you should see comments like this in the shell:
- Specifies the sh interpreter
#! /bin/shCopy the code
- Specify the bash interpreter
#! /bin/bashCopy the code
Pay attention to
The above method of specifying the interpreter is common, but sometimes you may also see the following:
#! /usr/bin/env bashCopy the code
The benefit of this is that the system automatically looks for the program you specify (bash in this case) in the PATH environment variable. You should use this notation as much as possible compared to the first notation, because the path of the program is uncertain. As an added benefit, the operating system’s PATH variable can be configured to point to another version of the program. For example, after installing a new version of bash, we might “hide” the old version by adding its PATH to PATH. If you just use #! /bin/bash, then the system selects the older version of bash to execute the script. /usr/bin/env bash, the new version is used.
1.4. Model
The shell has two modes: interactive and non-interactive.
Interactive mode
In simple terms, you can think of the shell’s interactive mode as executing the command line.
The shell is in interactive mode when you see something like this:
user@host:~$
Copy the code
Next, you can type a series of Linux commands such as ls, grep, CD, mkdir, rm, and so on.
Non-interactive mode
In simple terms, you can think of the shell’s non-interactive mode as executing shell scripts.
In non-interactive mode, the shell reads a command from a file or pipe and executes it.
When the shell interpreter finishes executing the last command in the file, the shell process terminates and returns to the parent process.
You can make the shell run in non-interactive mode with the following command:
sh /path/to/script.sh
bash /path/to/script.sh
source /path/to/script.sh
./path/to/script.sh
Copy the code
In the example above, script.sh is a plain text file that contains commands that the shell interpreter can recognize and execute, and sh and bash are shell interpreter programs. You can create script.sh using any editor you like (vim, Nano, Sublime Text, Atom, etc.).
Where, source /path/to/script.sh and./path/to/script.sh are equivalent.
In addition, you can execute scripts directly by adding executable permissions to files using the chmod command:
chmod +x /path/to/script.sh # Give execute permission to the script
/path/to/test.sh
Copy the code
This method requires that the first line of the script file must indicate the program to run the script. For example:
: Keyboard: Example source code Helloworld.sh
#! /usr/bin/env bash
echo "Hello, world!"
Copy the code
In the example above, we used the useful command echo to print the string to the screen.
Basic grammar
2.1. The interpreter
Although I mentioned the #! , but in the spirit of saying important things three times, here it is again:
In shell scripts, #! Tell the system that the program specified in the following path is the Shell interpreter that interprets the script file. #! It’s called a shebang (also known as a Hashbang).
#! Determines that the script can be executed as a stand-alone executable without having to type sh, bash, Python, PHP, etc. before the terminal.
You can specify shell interpreter as bash in either of the following ways. The second way is better
#! /bin/bash
#! /usr/bin/env bashCopy the code
2.2. The annotation
Comments can explain what your code does and why.
In shell syntax, comments are special statements that are ignored by the shell interpreter.
- One-line comments – to
#
The beginning, the end of the line. - Multi-line comments – to
:<<EOF
The beginning,EOF
The end.
: Keyboard: Example source code comment-demo.sh
# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
Shell comment example
# author: zp
# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
# echo 'This is a single line comment'
########## This is the dividing line ##########
:<<EOF
echo 'This is a multi-line comment.'
echo 'This is a multi-line comment.'
echo 'This is a multi-line comment.'
EOF
Copy the code
2.3. The echo
Echo is used for the output of strings.
Output a normal string:
echo "hello, world"
# Output: hello, world
Copy the code
Output a string containing variables:
echo "hello, \"zp\""
# Output: hello, "zp"
Copy the code
Output a string containing variables:
name=zp
echo "hello, \"${name}\ ""
# Output: hello, "zp"
Copy the code
Output a string with a newline:
# Prints a string with newlines
echo "YES\nNO"
# Output: YES\nNO
echo -e "YES\nNO" # -e enables escape
# Output:
# YES
# NO
Copy the code
Print a string with no newlines:
echo "YES"
echo "NO"
# Output:
# YES
# NO
echo -e "YES\c" # -e turns on escape \c without line feed
echo "NO"
# Output:
# YESNO
Copy the code
The output is redirected to a file
echo "test" > test.txt
Copy the code
Output execution result
echo `pwd`
# Output:(current directory path)
Copy the code
: Keyboard: Example source code echo-demo.sh
2.4. The printf
Printf is used to format the output string.
By default, printf does not automatically add a newline as echo does. If you need a newline, you can manually add \n.
: Keyboard: Example source code printf-demo.sh
# quotes
printf '%d %s\n' 1 "abc"
# Output:1 abc
# double quotation marks
printf "%d %s\n" 1 "abc"
# Output:1 abc
# no quotes
printf %s abcdef
# Output: abcdef(no line feed)
The # format specifies only one argument, but any additional arguments are still printed in that format
printf "%s\n" abc def
# Output:
# abc
# def
printf "%s %s %s\n" a b c d e f g h i j
# Output:
# a b c
# d e f
# g h i
# j
If there are no arguments, then %s is NULL and %d is 0
printf "%s and %d \n"
# Output:
# and 0
# Format output
printf "%-10s %-8s %-4s\n"Name gender weight kgprintf - 8-10 "% s % s % 4.2 f \ n"The guo jing male 66.1234printf - 8-10 "% s % s % 4.2 f \ n"Yang2 guo4 male 48.6543printf - 8-10 "% s % s % 4.2 f \ n"Guo Fu female 47.9876# Output:
Name gender weight kg
Guo Jing, Nan 66.12
# Yang Guo male 48.65
# Guo Fu Female 47.99
Copy the code
Escape character of printf
The sequence | instructions |
---|---|
\a |
Warning character, usually the ASCII BEL character |
\b |
back |
\c |
Suppress (do not display) any ending newline characters in the output (valid only in the argument string controlled by the %b format indicator), and any characters left in the argument, any subsequent arguments, and any characters left in the format string are ignored |
\f |
FormFeed |
\n |
A newline |
\r |
Carriage return |
\t |
Horizontal TAB |
\v |
Vertical TAB |
\ \ |
A literal backslash character |
\ddd |
A character representing a 1 – to 3-digit octal value. Valid only in the format string |
\0ddd |
Octal value characters representing 1 to 3 digits |
3. The variable
As with many programming languages, you can create variables in bash.
There are no data types in Bash, and variables in Bash can hold a number, a character, a string, and so on. There is no need to declare variables in advance; assigning a value to a variable creates the variable directly.
3.1. Variable naming principles
- The name can contain only letters, digits, and underscores (_). The first character cannot start with a digit.
- An underscore (_) can be used.
- No punctuation.
- You cannot use keywords in bash (use the help command to view reserved keywords).
3.2. Declare variables
The syntax for accessing variables is: ${var} and $var.
Curly braces around variable names are optional. They are used to help the interpreter identify variable boundaries, so they are recommended.
word="hello"
echo ${word}
# Output: hello
Copy the code
3.3. Read-only variables
Using the readonly command, you can define a variable as read-only. The value of a read-only variable cannot be changed.
rword="hello"
echo ${rword}
readonly rword
# rword="bye
Copy the code
3.4. Delete variables
The unset command is used to delete variables. A variable that has been deleted cannot be used again. The unset command cannot delete read-only variables.
dword="hello" # Declare variables
echo ${dword} # Output variable values
# Output: hello
unset dword # Delete variable
echo ${dword}
# Output: (empty)
Copy the code
3.5. Variable types
- Local variables – Local variables are variables that are valid only within a script. They cannot be accessed by other programs or scripts.
- The environment variable– Environment variables are visible to all programs or scripts in the current shell session. Creating them is similar to creating local variables, but using
export
Shell scripts can also define environment variables.
Common environment variables:
variable | describe |
---|---|
$HOME |
The user directory of the current user |
$PATH |
A semicolon-separated list of directories into which the shell looks for commands |
$PWD |
Current working directory |
$RANDOM |
An integer between 0 and 32767 |
$UID |
The value is the ID of the current user |
$PS1 |
Main system input prompt |
$PS2 |
Secondary system input prompt |
Here is a more comprehensive list of Bash environment variables.
3.6. Variable example source code
⌨️ Example source code variable-demo.sh
4. The string
4.1. Single and double quotes
Shell strings can be in single quotes ”, double quotes ” or no quotes.
- Features of single quotation marks
- Variables are not recognized in single quotes
- Single quotes are not allowed within single quotes (escape characters are not allowed), but can be used in pairs as string concatenation.
- Features of double quotation marks
- Identify variables in double quotes
- Escape characters can appear in double quotes
Above all, double quotation marks are recommended.
4.2. Concatenation of strings
# use single quotation marks
name1='white'
str1='hello, '${name1}' '
str2='hello, ${name1}'
echo ${str1}_${str2}
# Output:
# hello, white_hello, ${name1}
# use double quotation marks
name2="black"
str3="hello, "${name2}""
str4="hello, ${name2}"
echo ${str3}_${str4}
# Output:
# hello, black_hello, black
Copy the code
4.3. Get the string length
text="12345"
echo ${#text}
# Output:
# 5
Copy the code
4.4. Intercept substrings
text="12345"
echo ${text:2:2}
# Output:
# 34
Copy the code
Intercepts two characters, starting with the third character
4.5. Find substrings
#! /usr/bin/env bash
text="hello"
echo `expr index "${text}" ll`
# Execute: ./str-demo5.sh
# Output:
# 3
Copy the code
Look for the starting position of the LL subcharacter in the Hello string.
4.6. String example source code
⌨️ Example source code string-demo.sh
An array of 5.
Bash supports only one-dimensional arrays.
Array indices start at 0 and can be integers or arithmetic expressions whose value should be greater than or equal to 0.
5.1. Creating arrays
# Different ways to create arrays
nums=([2]=2 [0]=0 [1]=1)
colors=(red yellow "dark blue")
Copy the code
5.2. Accessing array elements
- Accessing a single element of an array:
echo ${nums[1]}
# Output: 1
Copy the code
- Access all elements of an array:
echo ${colors[*]}
# Output: red yellow dark blue
echo ${colors[@]}
# Output: red yellow dark blue
Copy the code
There is an important (and subtle) difference between the two lines above:
To print a single line for each element in the array, we use the printf command:
printf "+ %s\n" ${colors[*]}
# Output:
# + red
# + yellow
# + dark
# + blue
Copy the code
Why are dark and blue on each line? Try wrapping it in quotation marks:
printf "+ %s\n" "${colors[*]}"
# Output:
# + red yellow dark blue
Copy the code
Now all the elements are printed on one line — which is not what we want! Let’s try ${colors[@]}
printf "+ %s\n" "${colors[@]}"
# Output:
# + red
# + yellow
# + dark blue
Copy the code
Within quotes, ${colors[@]} extends each element in the array to a single parameter; Whitespace in array elements is preserved.
- Access partial elements of an array:
echo ${nums[@]:0:2}
# Output:
# 0 1
Copy the code
In the example above, ${array[@]} is extended to the entire array, and :0:2 takes all the elements of length 2 from 0.
5.3. Accessing array length
echo ${#nums[*]}
# Output:
# 3
Copy the code
5.4. Add elements to an array
Adding elements to an array is also simple:
colors=(white "${colors[@]}" green black)
echo ${colors[@]}
# Output:
# white red yellow dark blue green black
Copy the code
In the example above, ${colors[@]} is extended to the entire array and substituted into the compound assignment statement, and then the assignment to colors of the array overrides its original value.
5.5. Remove elements from an array
To remove an element from an array, use the unset command:
unset nums[0]
echo ${nums[@]}
# Output:
# 1 2
Copy the code
5.6. Array sample source code
: Keyboard: Example source code Array-demo.sh
6. Operator
6.1. Arithmetic operators
The following table lists the common arithmetic operators, assuming that the variable x is 10 and the variable y is 20:
The operator | instructions | For example, |
---|---|---|
+ | add | expr $x + $y That’s 30. |
– | subtraction | expr $x - $y So it’s minus 10. |
* | The multiplication | expr $x * $y That’s 200. |
/ | division | expr $y / $x That’s 2. |
% | Take more than | expr $y % $x That’s 0. |
= | The assignment | x=$y Assigns the value of the variable y to x. |
= = | The same. Used to compare two numbers. Returns true if they are the same. | [ $x == $y ] Returns false. |
! = | Is not equal. Used to compare two numbers; return true if they are different. | [ $x != $y ] Returns true. |
$x==$y; $x==$y; $x==$y; $x==$y;
: Keyboard: Example source operator-demo.sh
x=10
y=20
echo "x=${x}, y=${y}"
val=`expr ${x} + ${y}`
echo "${x} + ${y} = $val"
val=`expr ${x} - ${y}`
echo "${x} - ${y} = $val"
val=`expr ${x}A \ *${y}`
echo "${x} * ${y} = $val"
val=`expr ${y} / ${x}`
echo "${y} / ${x} = $val"
val=`expr ${y} % ${x}`
echo "${y} % ${x} = $val"
if [[ ${x}= =${y} ]]
then
echo "${x} = ${y}"
fi
if [[ ${x}! =${y} ]]
then
echo "${x}! =${y}"
fi
# Execute: ./operator-demo.sh
# Output:
# x=10, y=20
# 10 + 20 = 30
# 10-20 = -10
# 10 * 20 = 200
# 20/10 = 2
# 20%10 = 0
# 10! = 20
Copy the code
6.2. Relational operators
Relational operators only support numbers, not strings, unless the value of the string is a number.
The following table lists the commonly used relational operators, assuming the variable x is 10 and the variable y is 20:
The operator | instructions | For example, |
---|---|---|
-eq |
Tests if two numbers are equal. If they are, return true. | [ $a -eq $b ] Returns false. |
-ne |
Checks if two numbers are equal. If they are not, return true. | [ $a -ne $b ] Returns true. |
-gt |
Checks if the number on the left is greater than the number on the right, and returns true if it is. | [ $a -gt $b ] Returns false. |
-lt |
Checks if the number on the left is less than the number on the right, and returns true if it is. | [ $a -lt $b ] Returns true. |
-ge |
Checks if the number on the left is greater than or equal to the number on the right, and returns true if it is. | [ $a -ge $b ] Returns false. |
-le |
Checks if the number on the left is less than or equal to the number on the right, and returns true if it is. | [ $a -le $b ] Returns true. |
: Keyboard: Example source operator-demo2.sh
x=10
y=20
echo "x=${x}, y=${y}"
if [[ ${x} -eq ${y}]].then
echo "${x} -eq ${y}X = y"
else
echo "${x} -eq ${y}X does not equal y"
fi
if [[ ${x} -ne ${y}]].then
echo "${x} -ne ${y}X does not equal y"
else
echo "${x} -ne ${y}X = y"
fi
if [[ ${x} -gt ${y}]].then
echo "${x} -gt ${y}X is greater than y"
else
echo "${x} -gt ${y}X is not greater than y"
fi
if [[ ${x} -lt ${y}]].then
echo "${x} -lt ${y}X < y"
else
echo "${x} -lt ${y}X is not less than y"
fi
if [[ ${x} -ge ${y}]].then
echo "${x} -ge ${y}X is greater than or equal to y"
else
echo "${x} -ge ${y}X < y"
fi
if [[ ${x} -le ${y}]].then
echo "${x} -le ${y}X is less than or equal to y"
else
echo "${x} -le ${y}X is greater than y"
fi
# Execute: ./operator-demo2.sh
# Output:
# x=10, y=20
Eq 20: x does not equal y
# 10 -ne 20: x does not equal y
# 10 -gt 20: x is not greater than y
# 10 -lt 20: x is less than y
# 10-ge 20: x is less than y
# 10 -le 20: x is less than or equal to y
Copy the code
6.3. Boolean operators
The following table lists the common Boolean operators, assuming that the variable x is 10 and the variable y is 20:
The operator | instructions | For example, |
---|---|---|
! |
No operation, return false if the expression is true, or true otherwise. | [ ! false ] Returns true. |
-o |
Returns true if one of the expressions is true. | [ $a -lt 20 -o $b -gt 100 ] Returns true. |
-a |
Returns true if both expressions are true. | [ $a -lt 20 -a $b -gt 100 ] Returns false. |
:keyboard: Example source operator-demo3.sh
x=10
y=20
echo "x=${x}, y=${y}"
if [[ ${x}! =${y}]].then
echo "${x}! =${y}X does not equal y"
else
echo "${x}! =${y}X = y"
fi
if [[ ${x} -lt 100 && ${y} -gt15]];then
echo "${x}Less than 100 and${y}> 15: returns true"
else
echo "${x}Less than 100 and${y}> 15: return false"
fi
if [[ ${x} -lt100 | |${y} -gt100]];then
echo "${x}Less than 100 or${y}> 100: returns true"
else
echo "${x}Less than 100 or${y}> 100: return false"
fi
if [[ ${x} -lt5 | |${y} -gt100]];then
echo "${x}Less than 5 or${y}> 100: returns true"
else
echo "${x}Less than 5 or${y}> 100: return false"
fi
# Execute: ./operator-demo3.sh
# Output:
# x=10, y=20
# 10! = 20: x does not equal y
# 10 less than 100 and 20 greater than 15: returns true
# 10 less than 100 or 20 greater than 100: returns true
# 10 < 5 or 20 > 100: returns false
Copy the code
6.4. Logical operators
The following describes the Shell’s logical operators, assuming that the variable x is 10 and the variable y is 20:
The operator | instructions | For example, |
---|---|---|
&& |
The logic of the AND | [[ ${x} -lt 100 && ${y} -gt 100 ]] Returns false |
|| |
The logic of the OR | [[ ${x} -lt 100 || ${y} -gt 100 ]] Returns true |
: Keyboard: Example source operator-demo4.sh
x=10
y=20
echo "x=${x}, y=${y}"
if [[ ${x} -lt 100 && ${y} -gt100]]then
echo "${x} -lt 100 && ${y}-gt 100 returns true"
else
echo "${x} -lt 100 && ${y}-gt 100 returns false"
fi
if [[ ${x} -lt100 | |${y} -gt100]]then
echo "${x} -lt 100 || ${y}-gt 100 returns true"
else
echo "${x} -lt 100 || ${y}-gt 100 returns false"
fi
# Execute: ./operator-demo4.sh
# Output:
# x=10, y=20
# 10-lt 100 && 20-gt 100 returns false
20 # 10 - lt 100 | | - gt 100 returns true
Copy the code
6.5. String operators
The following table lists the commonly used string operators, assuming variable A is “ABC” and variable B is “efg” :
The operator | instructions | For example, |
---|---|---|
= |
Checks if two strings are equal. If they are, return true. | [ $a = $b ] Returns false. |
! = |
Checks if two strings are equal. If they are not, return true. | [ $a != $b ] Returns true. |
-z |
Checks if the string length is 0. If 0, returns true. | [ -z $a ] Returns false. |
-n |
Checks if the string length is 0. Returns true if it is not. | [ -n $a ] Returns true. |
str |
Checks if the string is empty. Returns true if it is not. | [ $a ] Returns true. |
: Keyboard: Example source operator-demo5.sh
x="abc"
y="xyz"
echo "x=${x}, y=${y}"
if [[ ${x} = ${y}]].then
echo "${x} = ${y}X = y"
else
echo "${x} = ${y}X does not equal y"
fi
if [[ ${x}! =${y}]].then
echo "${x}! =${y}X does not equal y"
else
echo "${x}! =${y}X = y"
fi
if [[ -z ${x}]].then
echo "-z ${x}: string length 0"
else
echo "-z ${x}: string length is not 0"
fi
if [[ -n "${x}"]].then
echo "-n ${x}: string length is not 0"
else
echo "-n ${x}: string length 0"
fi
if [[ ${x}]].then
echo "${x}: the string is not empty"
else
echo "${x}: the string is empty"
fi
# Execute: ./operator-demo5.sh
# Output:
# x=abc, y=xyz
# ABC = xyz: x does not equal y
# abc ! = xyz: x does not equal y
# -z ABC: The length of the string is not 0
# -n ABC: The length of the string is not 0
# ABC: The string is not empty
Copy the code
6.6. File test operators
The file test operator is used to detect various properties of Unix files.
Attribute detection is described as follows:
The operator | instructions | For example, |
---|---|---|
-b file | Checks if the file is a block device file and returns true if it is. | [ -b $file ] Returns false. |
-c file | Checks if the file is a character device file and returns true if it is. | [ -c $file ] Returns false. |
-d file | Checks if the file is a directory and returns true if it is. | [ -d $file ] Returns false. |
-f file | Checks if the file is a normal file (neither a directory nor a device file) and returns true if it is. | [ -f $file ] Returns true. |
-g file | Checks if the file has the SGID bit set, and returns true if so. | [ -g $file ] Returns false. |
-k file | Checks whether the file has Sticky bits set and returns true if so. | [ -k $file ] Returns false. |
-p file | Checks if the file is a named pipe and returns true if it is. | [ -p $file ] Returns false. |
-u file | Checks if the file has the SUID bit set and returns true if so. | [ -u $file ] Returns false. |
-r file | Checks whether the file is readable and returns true if it is. | [ -r $file ] Returns true. |
-w file | Checks if the file is writable and returns true if it is. | [ -w $file ] Returns true. |
-x file | Checks whether the file is executable and returns true if it is. | [ -x $file ] Returns true. |
-s file | Checks if the file is empty (if the file size is greater than 0), returns true if it is not empty. | [ -s $file ] Returns true. |
-e file | Detects whether the file (including the directory) exists and returns true if it does. | [ -e $file ] Returns true. |
: Keyboard: Example source operator-demo6.sh
file="/etc/hosts"
if [[ -r ${file}]].then
echo "${file}File readable ""
else
echo "${file}File unreadable"
fi
if [[ -w ${file}]].then
echo "${file}Document writable"
else
echo "${file}File cannot be written."
fi
if [[ -x ${file}]].then
echo "${file}File executable ""
else
echo "${file}File unexecutable"
fi
if [[ -f ${file}]].then
echo "${file}File is a common file ""
else
echo "${file}File is a special file"
fi
if [[ -d ${file}]].then
echo "${file}File is a directory."
else
echo "${file}File is not a directory."
fi
if [[ -s ${file}]].then
echo "${file}File not empty"
else
echo "${file}File is empty ""
fi
if [[ -e ${file}]].then
echo "${file}File exists ""
else
echo "${file}File does not exist."
fi
# Execute: ./operator-demo6.sh
The Output may vary according to the actual situation of the file.
The /etc/hosts file is readable
The /etc/hosts file is writable
The # /etc/hosts file is not executable
The # /etc/hosts file is a common file
# /etc/hosts file is not a directory
The /etc/hosts file is not empty
# /etc/hosts file exists
Copy the code
7. Control statements
7.1. Conditional statements
As with other programming languages, conditional statements in Bash allow us to determine whether an operation will be executed. The result depends on an expression wrapped in [[]].
Expressions wrapped in [[]] ([] in sh) are called detection commands or primitives. These expressions help us detect the result of a condition. This is where you’ll find the answer to the difference between single and double brackets in bash.
There are two different conditional expressions: if and case.
if
(1) If statement
If is used in the same way as any other language. If the expression in brackets is true, then the code between then and FI is executed. Fi marks the end of the conditional block.
Write # in one line
if[[1-eq1]];then echo "1 -eq 1 result is: true"; fi
# Output: 1 -eq 1 result is: true
Write the # in multiple lines
if [[ "abc" -eq "abc" ]]
then
echo ""abc" -eq "abc" result is: true"
fi
# Output: abc -eq abc result is: true
Copy the code
(2) If else statement
Again, we can use if.. Else statements, such as:
if[[2-ne1]];then
echo "true"
else
echo "false"
fi
# Output: true
Copy the code
(3) If elif else statement
Sometimes, if.. Can’t meet our requirements. Don’t forget the if.. elif.. Else is easy to use.
x=10
y=20
if [[ ${x} > ${y}]].then
echo "${x} > ${y}"
elif [[ ${x} < ${y}]].then
echo "${x} < ${y}"
else
echo "${x} = ${y}"
fi
# Output: 10 < 20
Copy the code
: Keyboard: Example source code if-demo.sh
case
If you are faced with many situations and need to take different actions, then using case is more useful than nested ifs. Using case to solve complex conditional judgments looks something like this:
: Keyboard: Example source code case-demo.sh
exec
case ${oper} in
"+")
val=`expr ${x} + ${y}`
echo "${x} + ${y} = ${val}"
;;
"-")
val=`expr ${x} - ${y}`
echo "${x} - ${y} = ${val}"
;;
"*")
val=`expr ${x}A \ *${y}`
echo "${x} * ${y} = ${val}"
;;
"/")
val=`expr ${x} / ${y}`
echo "${x} / ${y} = ${val}"
;;
*)
echo "Unknown oper!"
;;
esac
Copy the code
Each case is an expression that matches a pattern. | used to split multiple patterns,) used to end a pattern sequence. The command corresponding to the first matching pattern will be executed. * represents any pattern that does not match the given pattern above. Between the command block to use; Space.
7.2. Loop statements
Loops are not surprising. As in other programming languages, loops in bash are blocks of code that iteratively execute as long as the control condition is true.
There are four types of loops in Bash: for, while, until, and SELECT.
for
cycle
For is very much like its C sister. It looks like this:
for arg in elem1 elem2 ... elemN
do
# # #
done
Copy the code
During each loop, the arG is assigned values from elem1 through elemN. These values can also be wildcard or curly brace extensions.
Of course, we could write the for loop on one line, but this would require a semicolon to precede the do, like this:
for i in{1.. 5};do echo $i; done
Copy the code
Also, if you feel that for.. in.. Do is a little weird for you, so you can also use for like C, like:
for (( i = 0; i < 10; i++ )); do
echo $i
done
Copy the code
For comes in handy when we want to do the same for all files in a directory. For example, if we wanted to move all.bash files to the script folder and give them executable permissions, our script could read:
DIR=/home/zp
for FILE in ${DIR}/*.sh; do
mv "$FILE" "${DIR}/scripts"
done
# copy all sh files in /home/zp directory to /home/zp/scripts
Copy the code
: Keyboard: Example source code for-demo.sh
while
cycle
The while loop detects a condition and executes a sequence of commands as long as the condition is true. The condition being tested is similar to if.. The primitives used in then are the same. So a while loop would look like this:
while [[ condition ]]
do
# # #
done
Copy the code
As with the for loop, if we put the do on one line with the condition being tested, we must add a semicolon before the do.
Here’s an example:
### Square every number between 0 and 9
x=0
while [[ ${x} -lt10]];do
echo $((x * x))
x=$((x + 1))
done
# Output:
# 0
# 1
# 4
# 9
# 16
# 25
# 36
# 49
# 64
# 81
Copy the code
: Keyboard: Example source code while-demo.sh
until
cycle
The until loop is the opposite of the while loop. It also checks for a test condition like while, but executes as long as the condition is false:
x=0
until [[ ${x} -ge 5 ]]; do
echo ${x}
x=`expr ${x}+ 1 `done
# Output:
# 0
# 1
# 2
# 3
# 4
Copy the code
: Keyboard: Example source code until-demo.sh
select
cycle
The select loop helps us organize a user menu. Its syntax is almost identical to the for loop:
select answer in elem1 elem2 ... elemN
do
# # #
done
Copy the code
Select will print elem1.. The elemns and their serial numbers come to the screen, after which the user is prompted for input. You usually see $? (PS3 variable). The user’s selection result will be saved in the Answer. If the answer is one in 1.. N, then the statement will be executed, followed by the next iteration — we can use the break statement if we don’t want this.
A possible instance might look like this:
#! /usr/bin/env bash
PS3="Choose the package manager: "
select ITEM in bower npm gem pip
do
echo -n "Enter the package name: " && read PACKAGE
case ${ITEM} in
bower) bower install ${PACKAGE} ;;
npm) npm install ${PACKAGE} ;;
gem) gem install ${PACKAGE} ;;
pip) pip install ${PACKAGE} ;;
esac
break # Avoid infinite loops
done
Copy the code
This example starts by asking the user what package manager he wants to use. Next, you are asked what packages you want to install, and finally you perform the installation.
Running this script yields the following output:
$ ./my_script
1) bower
2) npm
3) gem
4) pip
Choose the package manager: 2
Enter the package name: gitbook-cli
Copy the code
: Keyboard: Example source select-demo.sh
break
和 continue
If you want to prematurely end a loop or skip a loop execution, you can use the shell’s break and continue statements to do so. They can be used in any loop.
The break statement is used to prematurely end the current loop.
The continue statement is used to skip an iteration.
: Keyboard: Example source code break-demo.sh
# Find the first positive integer within 10 that divides 2 and 3
i=1
while [[ ${i} -lt10]];do
if [[ $((i % 3)) -eq 0 ]] && [[ $((i % 2)) -eq0]];then
echo ${i}
break;
fi
i=`expr ${i}+ 1 `done
# Output: 6
Copy the code
: Keyboard: Example source code continue-demo.sh
Print odd numbers up to 10
for (( i = 0; i < 10; i ++ )); do
if [[ $((i % 2)) -eq0]];then
continue;
fi
echo ${i}
done
# Output:
# 1
# 3
# 5
# 7
# 9
Copy the code
8. Function
The bash function definition syntax is as follows:
[ function ] funname [()] {
action;
[returnint; ] }Copy the code
Bulbs: details:
- When a function is defined,
function
Keywords are optional.- Function return value -return Returns the value returned by a function. The return value can only be an integer (0-255). If you do not add a return statement, the shell returns the result of the last command.
- The return value from a function passes after the function is called
$?
To obtain.- All functions must be defined before they are used. This means that the function must be placed at the beginning of the script until it is first discovered by the shell interpreter. A function is called only by its function name.
: Keyboard: Example source code function-demo.sh
#! /usr/bin/env bash
calc(){
PS3="choose the oper: "
select oper in+ - \ * /# Generate operator selection menu
do
echo -n "enter first num: " && read x # Read input parameters
echo -n "enter second num: " && read y # Read input parameters
exec
case ${oper} in
"+")
return $((${x} + ${y}));"-")
return $((${x} - ${y}));"*")
return $((${x} * ${y}));"/")
return $((${x} / ${y})); *)echo "${oper} is not support!"
return0;;esac
break
done
}
calc
echo "the result is: $?" # $? Gets the value returned by the calc function
Copy the code
Execution result:
/ $.function-demo.sh
1) +
2) -
3) *
4) /
choose the oper: 3
enter first num: 10
enter second num: 10
the result is: 100
Copy the code
8.1. Positional parameters
Positional arguments are variables created when a function is called and passed arguments to it.
Variation table of positional parameters:
variable | describe |
---|---|
$0 |
The name of the script |
The $1... $9 |
List of parameters 1 through 9 |
The ${10}... ${N} |
The 10th to N parameter list |
$* or $@ |
In addition to$0 All positional parameters outside |
$# |
Do not include$0 Number of positional parameters within |
$FUNCNAME |
Function name (value only inside the function) |
: Keyboard: Example source code function-demo2.sh
#! /usr/bin/env bash
x=0
if [[ -n The $1]].then
echo "The first argument is:The $1"
x=The $1
else
echo "The first argument is null."
fi
y=0
if [[ -n $2]].then
echo "The second parameter is:$2"
y=$2
else
echo "The second parameter is empty."
fi
paramsFunction() {echo "The first argument to the function is:The $1"
echo "The second argument to the function:$2"
}
paramsFunction ${x} ${y}
Copy the code
Execution result:
/ $.function-demo2.sh the first argument is empty. The second argument is empty. The first argument to the function is 0function-demo2.sh 10 20 The first argument is: 10. The second argument is: 20. The first parameter in the function is: 10Copy the code
Run./ varial-demo4. sh hello world, and then pass $1, $2… Read the first parameter, the second parameter…
8.2. Function processing parameters
In addition, there are several special characters used to handle arguments:
Processing parameters | instructions |
---|---|
$# |
Number of returned parameters |
$* |
Return all parameters |
? |
ID of the process where the script is running |
$! |
The ID number of the last process running in the background |
$@ |
Return all parameters |
$- |
Returns the current option used by the Shell. It has the same function as the set command. |
$? |
Function return value |
: Keyboard: Example source code function-demo3.sh
runner() {
return 0
}
name=zp
paramsFunction() {echo "The first argument to the function is:The $1"
echo "The second argument to the function:$2"
echo "Number of arguments passed to the script:$#"
echo "All parameters:"
printf "+ %s\n" "$*"
echo "ID of the current process in which the script is running:?"
echo "ID number of last process running in the background: $!"
echo "All parameters:"
printf "+ %s\n" "$@"
echo "Current option used by Shell: $-"
runner
echo "Return value from function runner: $?"
}
paramsFunction 1 "abc" "hello, \"zp\""
# Output:
The function takes the first argument: 1
The second input to the function is ABC
# Number of arguments passed to script: 3
# All parameters:
# + 1 abc hello, "zp"
# Script is running on process 26400
# ID of last process running in background:
# All parameters:
# + 1
# + abc
# + hello, "zp"
# Current option used by Shell: hB
The # runner function returns 0
Copy the code
9. The Shell extension
The extension occurs after a line of commands has been broken up into tokens. In other words, extensions are a mechanism for performing mathematical operations, storing the results of commands, and so on.
You can read more details about shell extensions if you are interested.
Curly brace extension
The curly bracket extension makes it possible to generate arbitrary strings. This is similar to filename extensions. Here’s an example:
echo beg{i,a,u}n ### begin began begun
Copy the code
Curly brace extensions can also be used to create an interval that can be iterated through.
echo{0.. 5}### 0 1 2 3 4 5
echo{00.. 8.. 2}### 00 02 04 06 08
Copy the code
Command substitution
Command substitution allows us to evaluate a command and replace its value with another command or variable assignment expression. When a command is surrounded by ‘ ‘or $(), a command substitution is performed. Here’s an example:
now=`date +%T`
### or
now=$(date +%T)
echo $now # # # 19:08:26
Copy the code
Count extension
In bash, performing arithmetic operations is very convenient. Arithmetic expressions must be wrapped in $(()). The format of arithmetic extensions is:
result=$(( ((10 + 5*3) - 7) / 2 ))
echo $result # # # 9
Copy the code
In arithmetic expressions, variables need not be prefixed with $:
x=4
y=7
echo $(( x + y )) # # # 11
echo $(( ++x + y++ )) # # # 12
echo $(( x + y )) # # # 13
Copy the code
Single and double quotes
There is an important difference between single and double quotation marks. In double quotes, variable references or command permutations are expanded. Not in single quotes. Here’s an example:
echo "Your home: $HOME" ### Your home: /Users/<username>
echo 'Your home: $HOME' ### Your home: $HOME
Copy the code
When local and environment variables contain Spaces, be careful how they are extended in quotes. As a random example, suppose we use echo to output the user’s input:
INPUT="A string with strange whitespace."
echo $INPUT ### A string with strange whitespace.
echo "$INPUT" ### A string with strange whitespace.
Copy the code
The first echo is called with five separate arguments — $INPUT is broken up into separate words, and echo prints a space between each word. In the second case, echo is called with just one argument (the entire value of $INPUT, including Spaces within it).
Here’s a more serious example:
FILE="Favorite Things.txt"
cat $FILE ### Try to output two files: 'Favorite' and 'things.txt'
cat "$FILE" ### output a file: 'Favorite things.txt'
Copy the code
Although this problem can be solved by renating the FILE to Favorite -things.txt, what if the value came from an environment variable, a positional argument, or another command (find, cat, etc.)? Therefore, if the input may contain Spaces, be sure to wrap the expression in quotes.
10. Streams and redirects
Bash has powerful tools for handling collaboration between programs. Using streams, we can send the output of one program to another program or file, so we can easily log or do whatever else we want.
Pipelines give us the opportunity to create a conveyor belt that makes it possible to control the execution of a program.
Learning how to use these powerful, advanced tools is very, very important.
10.1. Input and output streams
Bash takes input and produces output in the form of a sequence or stream of characters. These streams can be redirected to a file or to another stream.
There are three file descriptors:
code | The descriptor | describe |
---|---|---|
0 |
stdin |
The standard input |
1 |
stdout |
The standard output |
2 |
stderr |
Standard error output |
10.2. The redirection
Redirection allows us to control where the input to a command comes from and where the output goes. These operators are used when redirecting control flow:
Operator | Description |
---|---|
> |
Redirected output |
& > |
Redirect output and error output |
& > > |
Redirects output and error output in additional form |
< |
Redirected input |
<< |
Here documentgrammar |
<<< |
Here a string |
Here are some examples of using redirects:
The result of ### ls will be written to list.txt
ls -l > list.txt
Append the output to list.txt
ls -a >> list.txt
### All error messages are written to errors.txt
grep da * 2> errors.txt
### reads input from errors.txt
less < errors.txt
Copy the code
10.3. /dev/null
file
If you want to execute a command but do not want the output to appear on the screen, you can redirect the output to /dev/null:
$ command > /dev/null
Copy the code
/dev/null is a special file to which all content written is discarded; If you try to read from this file, nothing will be read. However, the /dev/null file is very useful, and redirecting the output of the command to it has the effect of “disallowing output”.
If you want to block stdout and stderr, you can write:
$ command > /dev/null 2>&1
Copy the code
11. Debug
The shell provides tools for debugging scripts.
If you want to run a script in debug mode, you can use a special option in its shebang:
#! /bin/bash options
Copy the code
Options are options that can change shell behavior. Here are some options that might be useful to you:
Short | Name | Description |
---|---|---|
-f |
noglob | Disable file name expansion (globbing) |
-i |
interactive | Let the script tointeractionmode |
-n |
noexec | Read the command, but do not execute it (syntax checking) |
-t |
– | Exit after the first command is executed |
-v |
verbose | Before executing each command, go tostderr Output the command |
-x |
xtrace | Before executing each command, go tostderr Prints the command and its extended parameters |
For example, if we specify -x in the script, for example:
#! /bin/bash -x
for (( i = 0; i < 3; i++ )); do
echo $i
done
Copy the code
This prints out the value of the variable and some other useful information to stdout:
$ ./my_script
+ (( i = 0 ))
+ (( i < 3 ))
+ echo 0
0
+ (( i++ ))
+ (( i < 3 ))
+ echo 1
1
+ (( i++ ))
+ (( i < 3 ))
+ echo 2
2
+ (( i++ ))
+ (( i < 3 ))
Copy the code
Sometimes we need a part of the debug script. In this case, it is convenient to use the set command. This command enables or disables options. Use -to enable an option, + to disable an option:
: Keyboard: Example source code debug-demo.sh
# to open the debug
set -x
for (( i = 0; i < 3; i++ )); do
printf ${i}
done
# to close the debug
set +x
# Output:
# + (( i = 0 ))
# + (( i < 3 ))
# + printf 0
# 0+ (( i++ ))
# + (( i < 3 ))
# + printf 1
# 1+ (( i++ ))
# + (( i < 3 ))
# + printf 2
# 2+ (( i++ ))
# + (( i < 3 ))
# + set +x
for i in{1.. 5};do printf ${i}; done
printf "\n"
# Output: 12345
Copy the code
12. More
: Notebook: This article has been filed to: “blog”
- Awesome -shell, list of shell resources
- Awesome -bash, list of bash resources
- bash-handbook
- Bash-guide is a basic bash guide
- Bash-it provides a reliable framework for your daily use, development, and maintenance of shell scripts and custom commands
- Dotfiles.github. IO, which has links to various dotFiles collections for bash and other shells and shell frameworks
- Runoob Shell tutorial
- Shellcheck is a static shell script analysis tool, which is essentially a bash/sh/ZSH Lint.
Finally, there are a lot of questions you can learn from under the bash TAB on Stack Overflow, and a good place to ask questions when you run into them.