Shell script operates in the same way as interpretive language. If you have a language foundation, it is very easy to learn shell script. However, shell is different from common languages. Some common functions need to be realized by combining some commands in shell
Tool recommendation
The Shell does not seem to have a customized IDE. It is recommended that VS Code be matched with the corresponding plug-in:
- Shellman intelligent prompt and automatic completion. There are trigger keywords to introduce common code fragments on the plug-in page. The author wrote the story of shellman's birth in Shellman reborn, which is very interesting
- Shellcheck syntax static check tool. After the plug-in is installed, shellcheck needs to be installed locally. Refer to shellcheck Installing. Mac OS can use brew install shellcheck. In this way, when writing a Shell, the syntax errors will be prompted in the form of wavy lines
- Shell format code sorting, Win shortcut: Alt + Shift + F, Mac OS shortcut: option + shift + F
- Run the Code Runner script, right-click Run Code, Win shortcut: Ctrl + Alt + N, Mac OS shortcut: control + option + N
Run shell script
New script: test sh
#!/usr/bin/env bash # Use echo to print strings or variables echo 'hello world'
You can run it with Code Runner, and it will output: hello world
In the first line of the Shell script, it is usually written #/ bin/bash this is Shebang, #! Followed by the absolute PATH of the interpreter with which the script will execute. Another way of writing is: #/ usr/bin/env bash, / usr/bin/env is the absolute PATH of the env command. The env command is used to display the existing environment variables in the system, including $PATH. Bash will be found in the directory contained in $PATH. The common command line interpreters are: SH, bash, Zsh (the default interpreter for Mac OS)
There are several ways to run under Linux or Unix like environment:
- First add execution permission to the script: Chmod + X test SH, and then run the script:/ test.sh, this method will read Shebang and execute the script with the specified interpreter
- sh test.sh, use the SH interpreter to execute the script. Of course, it can also be executed in other ways, such as bash test sh. The same as the first method, the current shell is the parent process, generates a child shell process (the child process will inherit the environment variables of the parent process), executes the script in the child shell, and the exited shell returns to the current shell after the script is executed
- Source point command mode: source test SH is equivalent to test.sh. Source lets the script execute in the current shell without generating new child processes. Use source to execute the script. The modification of environment variables in the script will affect the current shell, which is why we are modifying some configurations, such as ~ / Bashrc, execute source ~ / The configuration takes effect after bashrc
- Exec mode: if necessary, add execution permission to the script: Chmod + X test SH, execute exec/ test. SH also allows the script to execute on the same process without generating new child processes. The difference from source is that the process will be ended after the script execution is completed
Basic command
You can learn according to the [Bash Shell] Shell learning notes. This article is very detailed. This blog is also written after learning this article
Get input
Use the read command to get input from the standard input stream (stdin)
#!/usr/bin/env bash read var echo "${var}"
Run the script, enter any character and press enter to confirm. The entered value will be assigned to the variable var and the variable will be printed out
output
#!/usr/bin/env bash var=1 # Output variable echo ${var} # Some characters displayed in the output string need to be escaped echo "\"hello world\"" # "hello world" # Use the - e parameter for line feed: make the escape character take effect # Use \ n fold echo -e "newline\n"
You can also let the shell output characters of different colors. You can refer to: echo display content in shell script is colored
#!/usr/bin/env bash echo -e "\033[30m Black characters \033[0m" echo -e "\033[31m Red characters \033[0m" echo -e "\033[32m Green word \033[0m" echo -e "\033[33m Yellow word \033[0m" echo -e "\033[34m Blue word \033[0m" echo -e "\033[35m Purple character \033[0m" echo -e "\033[36m Sky blue character \033[0m" echo -e "\033[37m White words \033[0m"
Variable use
# =There must be no spaces on either side var="hello world" num=100 # This method can be used when referencing variables, but the following is recommended echo $var # It is recommended to use double quotation marks around string variables. Otherwise, if there are spaces in the variable string, the string will be segmented echo "$var" # If string splicing is involved, curly braces can be added around the variable name echo "Variable is: ${var}." # Set the variable to read-only, and an error will be reported if you modify it again readonly var # var="wolrd" # Delete variables. Variables decorated with readonly cannot be deleted unset num
During variable assignment, the naming rules of variable names are similar to those in other languages. Note that there can be no spaces on both sides of = during variable assignment
When using, add $before the variable name. It is recommended that all variables use ${} to use variables
operation
Arithmetic operation: Bash native does not support mathematical operation. awk and expr can be used
Note that the multiplication sign needs to be escaped: \ *, and there must be spaces on both sides of the operator
a=10 b=3 val=`expr $a + $b` echo "a + b : $val" val=`expr $a - $b` echo "a - b : $val" val=`expr $a \* $b` echo "a * b : $val" val=`expr $b / $a` echo "b / a : $val" val=`expr $b % $a` echo "b % a : $val"
Execute command
Both $() and ` ` (backquotes) can be used to execute commands and return the execution results. shellcheck recommends the first $() method
#!/usr/bin/env bash result=`date "+%Y-%m-%d"` echo "${result}" result=$(date "+%Y-%m-%d") echo "${result}"
operator
Relational operators only support numbers. If the string is a number, the relational operators include:
operator | meaning |
-eq | be equal to |
-ne | Not equal to |
-gt | greater than |
-lt | less than |
-ge | Greater equal to |
-le | Little equal to |
The conditional expression must be placed in [], and there must be spaces to the right of [and] to the left
List of Boolean operators:
operator | meaning |
! | wrong |
-o | Or (or) |
-a | And |
#!/usr/bin/env bash a="10" b="3" c=1 if [ ${a} -ne ${b} ] then echo "identical" else echo "inequality" fi if [ ${a} -gt ${b} -a ${b} -gt ${c} ] then echo "a > b & b > c" fi
Other common judgments:
- Directly put string variables in [], such as [${STR}], to judge whether the str string is not empty
- -F judge whether it is an ordinary file, for example: [- f $file]
- -d judge whether it is a folder, for example: [- d $file]
String interception
Format of character interception: ${string: Start: length}
The index starts from 0. You can omit: length, so it will be intercepted to the end. Note that the space should be empty after: otherwise: bad substitution may be prompted
#!/usr/bin/env bash string="hello world" echo ${string: 1 : 3} # ell # Intercept to the end echo ${string:1} # ello world
array
#!/usr/bin/env bash # 1. Define an array: use parentheses to declare it, separate it with "space" or line break arr=(1 2 3) strArr=( "first" "second" ) # 2. Read array: read by subscript, and the subscript is calculated from 0 echo "${arr[0]}" # Use * or @ to read all elements echo ${arr[*]} echo ${arr[@]} # Read array length read all elements preceded by # echo ${#arr[*]} echo ${#arr[@]} # Ergodic subscript for(( i=0;i<${#strArr[@]};i++)) do echo ${strArr[i]}; done; # for in traversal element for element in ${strArr[*]} do echo $element done # 3. Modify array elements strArr[0]="modify" echo ${strArr[0]} # 4. Delete element unset arr[1] echo ${#arr[*]} echo ${arr[*]} # 1 3 # ! When using unset, you should note that this does not really delete the element, but just empty the element. Therefore, using subscript traversal will cause problems, as shown below echo "Array traversal:" for(( i=0;i<${#arr[@]};i++)) do echo "index ${i} -> ${arr[i]}"; done; # index 0 -> 1 # index 1 -> # To solve the problem that unset cannot be deleted: reassign to a new array echo "Array traversal:" arr=( "${arr[@]}" ) for(( i=0;i<${#arr[@]};i++)) do echo "index ${i} -> ${arr[i]}"; done; # index 0 -> 1 # index 1 -> 3
Judgment statement
if and fi are used to define the boundary of judgment, and then, elif and else are used to define conditions
#!/usr/bin/env bash #!/usr/bin/env bash a=10 b=20 if [ $a == $b ] then echo "equal" else echo "Unequal" fi if [ $a == $b ] then echo "equal" elif [ $a -lt $b ] then echo "a less than b" else echo "Other situations" fi
function
When calling the function, we can pass in parameters and obtain parameters through $n. here n represents the index of the parameters to be obtained. When n > = 10, we need to use ${n} to obtain parameters
$# number of parameters passed to the function, $* and $@ show all parameters passed to the function, $? Indicates the return value of the function. It can also be used to obtain the exit status of the previous command. 0 will be returned for successful execution and 1 for failure
# Define function #!/usr/bin/env bash funWithParam(){ echo "Number of parameters: $#" # Number of parameters: 11 echo "All parameters passed to the function: $*" # All parameters passed to the function: 1 2 3 4 5 6 7 8 9 34 73 echo "$1" # 1 # Parameters exceeding 9 need to receive parameters with ${}, otherwise the value will be displayed directly echo "$10" # 10 echo "${11}" # 73 } # Calling function: the function name is directly followed by the parameter funWithParam 1 2 3 4 5 6 7 8 9 34 73 echo "$?" # 0
I / O redirection
Use > to redirect and output the data that should be output to the terminal to a file, > defaults to overwrite the file, and use > > to append and write the file
Use < to direct data entered from the keyboard by defau lt to input from a file
# The who command is used to display which users in the system are working on it # Enter the results into who txt who > who.txt # wc -l is used to calculate the number of lines of text wc -l < who.txt
Typically, each Unix/Linux command runs with three files open:
- Standard input (stdin): the file descriptor of stdin is 0, and Unix programs read data from stdin by default
- Standard output (stdout): the file descriptor of stdout is 1. Unix programs output data to stdout by default
- Standard error output (stderr): the file descriptor of stderr is 2, and Unix program will write error information to stderr stream
Therefore, we generally start the application in the background and output the log file using:
nohup java -jar xxx.jar >> nohup.log 2>&1 &
nohup: (no hang up) ensure that the corresponding process continues to run after exiting the account or closing the terminal
>> nohup.log: add Java - jar XXX The output of jar is appended to nohup. Jar Log file
2> & 1: add Java - jar XXX The standard error output of jar is also redirected to standard input
&: let the process run in the background
By default, command > file redirects stdout to file, and command < file redirects stdin to file.
If you want stderr to redirect to file, you can write this:
Pit carding
- During variable assignment, the naming rules of variable names are similar to those in other languages. Note that there can be no spaces on both sides of = during variable assignment
- The unset element of the array is not a real removal element
- When obtaining parameters, when n > = 10, ${n} needs to be used to obtain parameters
Common special Shell environment variables
- $$indicates the ID of the current Shell process, i.e. pid
- $0 represents the absolute path of the current script
- $# number of arguments passed to script or function
- $n parameters passed to script or function
- $? Exit status of last command
- $* and $@ are all parameters passed to a script or function
- $n represents any number from 1 to 9, which is passed to the parameter of the script or function at that position
Difference between $* and $@:
#!/usr/bin/env bash function asterisk () { echo "\"\$*\"" for var in "$*" do echo "$var" done } function mail () { echo "\"\$@\"" for var in "$@" do echo "$var" done } asterisk a b c mail a b c
output
"$*" a b c "$@" a b c
When $* and $@ are used directly, the effect is the same. They both receive a copy of data, as shown in the example above. What they receive is: A, B, C, a copy of data, separated by spaces. After double quotation marks, "$@" will treat each parameter as a separate piece of data