编程知识 cdmana.com

Detailed explanation of shell script programming for front end

My blog original link :https://chenfangxu.lap.360.cn/assistive-tools/shell/script.html


Shell Script (shell script), It's for Shell Write the script , The general file suffix is .sh.

Script interpreter

#! It's an agreed mark , It tells the system what interpreter the script needs to run , That is, what kind of shell.#! go by the name of shebang( Also known as Hashbang), For example, using bash:#! /bin/bash

Create a new one test.sh The file of , The contents are as follows :

#!/bin/bash

echo "Hello World!"

function Shell Script

The first way : As an executable

1、 At present test.sh There are no executable permissions , First, make the script file have execute permission .

#  Make the script file have execute permission 
chmod +x ./test.sh

2、 Execute the script

#  Execute the script , It should be noted that the directory should be marked 
./test.sh

#  It can also be used.  source  To execute the script , It's equivalent to the above , But you don't need the script to have execution rights 
source ./test.sh

Be careful : It must be written as ./test/sh , instead of test.sh . It's the same with other binary programs , direct writing test.sh,Linux The system will go to PATH I'm looking for a call test.sh Of , And only /bin, /sbin, /usr/bin, /usr/sbin Wait in PATH in . Your current directory is usually not in PATH in , So it's written as test.sh There's no command , Use ./test.sh Tell the system , Look for... In the current directory .

Run... In this way bash Script , The first line must be correct , So that the system (Shell Program ) Find the right interpreter . If you use the standard default shell, You can leave out the first line .

As interpreter parameters

Run the interpreter directly , The parameter is Shell The filename of the script .

/bin/bash test.sh

Scripts that run this way , You don't need to specify interpreter information on the first line , It's no use writing .

grammar

1、 notes

  • Single-line comments : With # start , To end of line .
  • Multiline comment : With :<<EOF start , To EOF end
#  This is a single line comment 

:<<EOF
 This is a multiline comment 
 This is a multiline comment 
EOF

If there is a piece of code to comment and uncomment frequently , It can be enclosed in curly brackets , Defined as a function , There's no place to call this function , This code will not execute , Achieved the same effect as annotation .

2、 Variable

Variable type

  • local variable : Local variables are variables that are only valid within a script . They can't be accessed by other programs and scripts .
  • environment variable : Environment variables are variables inherited from the parent process , For the current Shell All programs and scripts in the session are visible . Creating them is similar to creating local variables , But it uses export keyword ,shell Scripts can also define environment variables .
  • shell Variable ( System variables ):shell Variables are derived from shell Special variables for program settings .shell Some of the variables are environment variables , Some of them are local variables , These variables guarantee shell Normal operation of .

Variable Syntax

1、 Declare variables

You can use the equal sign operator to assign values to variables :varName=value,varName Is a variable name. ,value Is the value assigned to a variable .

Naming rules for variable names :

  • The first letter must be a letter (a-z,A-Z), The rest is in English letters only , Number underline
  • No spaces in between , You can use underscores , If there are spaces , You must use single or double quotation marks
  • You can't use punctuation
  • Out of commission shell keyword
#!/bin/bash

fruit=apple
count=5

Be careful :varName=value There are no spaces on either side of the equal sign of , If there is a space in the variable value , It needs to be enclosed in quotation marks .

2、 Access variables

The syntax of accessing variables is :${varName} and $varName, Curly braces outside variable names are optional , Add it or not , Curly braces are used to help the interpreter identify the boundaries of variables ( Curly brackets are recommended ).

#!/bin/bash

fruit=apple
count=5
echo "We have $count ${fruit}s"
# Output :We have 5 apples

because Shell Use white space to separate words , So in the above example, we need to add curly brackets to tell Shell The variable name here is fruit, instead of fruits

Be careful : When using single quotation marks , Variables are not expanded (expand), Still as it is . It means echo '$var' Will be displayed \$var. When using double quotes , If \$var It has been defined , that echo "$var" The value of the variable will be displayed , If there is no definition , Then nothing is shown .

3、 A read-only variable

Use readonly Commands can define variables as read-only variables , The value of a read-only variable cannot be changed

#!/bin/bash

fruit=apple
echo $fruit
readonly fruit
#fruit=banana  # If you let go of the comments , Error will be reported during execution 

4、 Delete variables

Use unset Command to delete variables , Variable cannot be used again after being deleted .unset Command cannot delete read-only variables

#!/bin/bash

fruit=apple
echo $fruit
# Output : apple

unset fruit
echo $fruit
# Output : ( empty )

Shell Special variables ( System variables )

The naming rules for variable names have been mentioned above , But there are also variables that contain other characters that have special meanings , Such variables are called special variables .

Variable meaning
$0 File name of the current script
$n Parameters passed to a script or function .n It's a number , Indicates the number of parameters . for example , The first parameter is \$1
$# Number of arguments passed to script or function
$* All parameters passed to a script or function
$@ All parameters passed to a script or function , By double quotes ("") Inclusion time , And \$\* not quite the same
$FUNCNAME The name of the function ( Only in functions )
$? Exit status of last command , Or the return value of a function
$- Show shell Current options used (flag), In the later extension, we will use
$$ At present Shell process ID. about Shell Script , It's the process of these scripts ID
$! The last process running in the background ID Number
Command line arguments : The parameters passed to the script at run time become parameters to the script , Command line parameters use $n Express .
#!/bin/bash

# ./test.sh

echo " file name :$0"
echo " The first command line argument :$1"
echo " The second command line argument :$2"
echo " All parameters passed in :$@"
echo " All parameters passed in :$*"
echo " The number of all parameters :$#"

Carry out orders :./test.sh Linux Shell, The result is :

 file name :./test.sh
 The first command line argument :Linux
 The second command line argument :Shell
 All parameters passed in :Linux Shell
 All parameters passed in :Linux Shell
 The number of all parameters :2

$? You can get the exit status of the previous command . So called exit status , Is the result of the last command . Exit status is a number , In general , Most commands are executed successfully and will return 0, Failure will return 1.$? It can also represent the return value of a function .

3、 character string

String quotes

shell Strings can use single quotes '' , You can also use double quotes "" , You can also use no quotes .

  • Single quotation marks : Don't recognize variables , Single quotation marks cannot appear in the middle of single quotation marks ( It doesn't work with escape characters ), Can appear in pairs to achieve string splicing .
name='world'

before='hello,'${name}'!' # Use single quotation marks to concatenate strings 
after='hello,${name}!'  # Variables in single quotation marks do not parse 

echo ${before}_${after}
#  Output :hello,world!_hello,${name}!
  • Double quotes : You can identify variables , Double quotation marks that are escaped with the escape character can appear in double quotation marks
name="\"shell\""  # Escaped double quotation marks are allowed within double quotation marks 

before="hello,"${name}"!" # Use double quotation marks to concatenate strings 
after="hello,${name}!" # Variables in double quotes will parse 

echo ${before}_${after}
#  Output :hello,"shell"!_hello,"shell"!
Set a string variable , The following are all operations on this variable
file=/dir1/dir2/dir3/my.file.txt

${#var}: Get the length of the variable value

echo ${#file}
#  Output :27

${varx}: The substring is intercepted by the index position

echo ${file:0:5} # Intercept the leftmost 5 Characters 
#  Output :/dir1

echo ${file:5:5} # From 6 Character start , Intercept 5 Characters 
#  Output :/dir2

${var#}、${var##}: Delete the value to the left of the string

echo ${file#*/} # Delete the first  /  And the string to the left of it 
#  Output :dir1/dir2/dir3/my.file.txt

echo ${file##*/} # Delete the last one  /  And the string to the left of it 
#  Output :my.file.txt

echo ${file#*.} # Delete the first  .  And the string to the left of it 
#  Output :file.txt

echo ${file##*.} # Delete the last one  .  And the string to the left of it 
#  Output :txt

${var%}、${var%%}: Delete the value to the right of the string

echo ${file%/*} # Delete the last one  /  And the string to the right of it 
#  Output :/dir1/dir2/dir3

echo ${file%%/*} # Delete the first  /  And the string to the right of it 
#  Output :( Null value )

echo ${file%.*} # Delete the last one  .  And the string to the right of it 
#  Output :/dir1/dir2/dir3/my.file

echo ${file%%.*} # Delete the first  .  And the string to the right of it 
# Output :/dir1/dir2/dir3/my

${var:-word}: If the variable var It's empty 、 Not defined or deleted (unset), Then the return word, But it doesn't change. var Value .

echo ${var:-"var is not set"}
# Output :var is not set

echo "var is ${var}"
# here  var  Still no definition , So the output :var is

${var:=word}: If the variable var It's empty 、 Not defined or deleted , Then the return word, And will var Is set to word.

echo ${var:="var is not set"}
# Output :var is not set

echo "var is ${var}"
# here  var  Has been defined as var is not set  了 , So the output :var is var is not set

${var:?message}: If the variable var It's empty 、 Not defined or deleted , Then send the message message Send to standard error output .

Can be used to detect variables var Whether it can be assigned normally . If this substitution appears in shell Script , Then the script will stop running .

${var:+word}: If the variable var Defined , Then the return word, But it doesn't change. var Value .

Array

An array is a variable that can store multiple values , These values can be referenced individually , It can also be referenced as an entire array . Array subscript from 0 Start , The subscript can be an integer or an arithmetic expression , Its value should be greater than or equal to 0.

Create array

numbers=(one two three four five)

# When creating an array, indicate the subscript 
colors=([1]=red [0]=yello [2]=blue)

Access array

Access individual elements

echo ${numbers[2]}
# Output :three

Access all elements of the array

echo ${colors[*]}
# Output :yello red blue

echo ${colors[@]}
# Output :yello red blue

${colors[*]} and ${colors[@]} There are subtle differences , When you output each element in an array on a separate line , Whether it's enclosed in quotation marks makes a difference , In quotation marks ,${colors[@]} Expand each element in the array to a single parameter , Spaces in array elements are preserved .

Accessing partial elements of array

# :0:2  Remove the array from 0 Start , The length is 2 Array elements of 
echo ${colors[@]:0:2}
# Output :yello red

Length of array

echo ${#colors[@]}
# Output :3

Adding elements to an array

colors=(white "${colors[@]}" green black)

echo ${colors[@]}
# Output :white yello red blue green black
echo ${#colors[@]}
# Output :6

Delete elements from array

unset colors[2]

echo ${colors[@]}
# Output :white yello blue green black
echo ${#colors[@]}
# Output :5

A complete code example :

#!/bin/bash


numbers=(one two three four five)

colors=([1]=red [0]=yello [2]=blue)

echo ${numbers[2]}

echo ${colors[*]}

echo ${colors[@]}

echo ${colors[@]:0:2}

echo ${#colors[@]}

colors=(white "${colors[@]}" green black)

echo ${colors[@]}

echo ${#colors[@]}

unset colors[2]

echo ${colors[@]}

echo ${#colors[@]}

Operator

Shell There are many operators in , Including arithmetic operators 、 Relational operator 、 Boolean operator 、 String operators and file testers .

Arithmetic operator

Native bash Simple mathematical operations are not supported , It is more commonly used with the help of expr To implement mathematical operations .

List of arithmetic operators , Variable a yes 10 Variable b yes 50

Operator explain give an example
+ Add expr ${a} + ${b} The result is 60
- Subtraction expr ${b} - ${a} The result is 40
\* Multiplication expr ${a} \\* ${b} The result is 500
/ division expr ${b} / ${a} The result is 5
% Remainder expr ${b} % ${a} The result is 0
= assignment a=$b It's a normal variable assignment

The sample code is as follows :

#!/bin/bash

a=10
b=50

value=`expr ${a} + ${b}`
echo "a + b = ${value}"

value=`expr ${b} - ${a}`
echo "b - a = ${value}"

value=`expr ${a} \* ${b}`
echo "a * b = ${value}"

value=`expr ${b} / ${a}`
echo "b / a = ${value}"

value=`expr ${b} % ${a}`
echo "b % a = ${value}"

# Output 
#a + b = 60
#b - a = 40
#a * b = 500
#b / a = 5
#b % a = 0

Be careful :

  1. Space between expression and operator , for example 1+1 It's wrong. , Must be written as 1 + 1
  2. The complete expression should be in back quotation marks ` encase
  3. Conditional expressions should be placed between square brackets , And there should be spaces , for example [${a}==${b}] It's wrong. , Must be written as [ ${a} == ${b} ]

Conditional operator ( Relational operator )

Relational operators only support numbers , String not supported , Unless the value of the string is a number .

List of relational operators , Variable a yes 10 Variable b yes 50

Operator explain give an example
-eq Check whether two numbers are equal , Equal return true [ ${a} -eq ${b} ] return false
-ne Check if two numbers are not equal , Unequal return true [ ${a} -ne ${b} ] return true
-gt Check whether the number on the left is greater than the number on the right , If it is , return true [ ${a} -gt ${b} ] return false
> Follow -gt equally , But because of compatibility issues , May be in [[]] Use in expressions [[ ${a} > ${b} ]] return false
-lt Check whether the number on the left is less than the number on the right , If it is , return true [ ${a} -lt ${b} ] return true
< Follow -lt equally , But because of compatibility issues , May be in [[]] Use in expressions [[ ${a} < ${b} ]] return true
-ge Check whether the number on the left is greater than or equal to the number on the right , If it is , return true [ ${a} -ge ${b} ] return false
-le Checks whether the number on the left is less than or equal to the number on the right , If it is , return true [ ${a} -le ${b} ] return true

The example code is as follows :

!/bin/bash

a=10
b=50

if [ ${a} -eq ${b} ]; then
  echo "${a} -eq ${b} : a  be equal to  b"
else
  echo "${a} -eq ${b} : a  It's not equal to  b"
fi
# Output :10 -eq 50 : a  It's not equal to  b

if [ ${a} -ne ${b} ]; then
  echo "${a} -ne ${b} : a  It's not equal to  b"
else
  echo "${a} -ne ${b} : a  be equal to  b"
fi
# Output :10 -ne 50 : a  It's not equal to  b

if [ ${a} -gt ${b} ]; then
  echo "${a} -gt ${b} : a  Greater than  b"
else
  echo "${a} -gt ${b} : a  Less than  b"
fi
# Output :10 -gt 50 : a  Less than  b
if [[ ${a} > ${b} ]]; then
  echo "${a} > ${b} : a  Greater than  b"
else
  echo "${a} > ${b} : a  Less than  b"
fi
# Output :10 > 50 : a  Less than  b

if [ ${a} -lt ${b} ]; then
  echo "${a} -lt ${b} : a  Less than  b"
else
  echo "${a} -lt ${b} : a  Greater than  b"
fi
# Output :10 -lt 50 : a  Less than  b
if [[ ${a} < ${b} ]]; then
  echo "${a} < ${b} : a  Less than  b"
else
  echo "${a} < ${b} : a  Greater than  b"
fi
# Output :10 < 50 : a  Less than  b

if [ ${a} -ge ${b} ]; then
  echo "${a} -ge ${b} : a  Greater than or equal to  b"
else
  echo "${a} -ge ${b} : a  Less than or equal to  b"
fi
# Output :10 -ge 50 : a  Less than or equal to  b

if [ ${a} -le ${b} ]; then
  echo "${a} -le ${b} : a  Less than or equal to  b"
else
  echo "${a} -le ${b} : a  Greater than or equal to  b"
fi
# Output :10 -le 50 : a  Less than or equal to  b

Conditional operator ( Boolean operator 、 Logical operators 、 String operators )

List of conditional operators , Variable a yes 10, Variable b yes 50, Variable x yes "abc", Variable y yes "efg"

Operator explain give an example
! Non operation [ ! false ] return true
-o Or operations [ ${a} -eq 10 -o ${b} -eq 100 ] return true
-a And operation [ ${a} -eq 10 -a ${b} -eq 50 ] return true
&& Follow -a similar , Logical AND, But you need to use [[]] expression [[ ${a} -eq 10 && ${b} -eq 50 ]] return true
= Check whether two numbers or strings are equal , Equal return true [ ${a} = ${b} ] return false
!= Check whether two numbers or strings are equal , Unequal return true [ ${a} != ${b} ] return true
== equal . Compare two numbers or strings , If equal returns true( It is not recommended to use , Compatibility issues ) [ ${a} == ${b} ] return false
-z Check if the string length is 0, by 0 return true [ -z ${x} ] return false
-n Check if the string length is 0, Not for 0 return true [ -n ${x} ] return true
var Check whether the variable exists or is not empty , Exist or not empty return true [ $s ] return false

The code example is as follows :

#!/bin/bash

a=10
b=50
x="abc"
y="edf"

# single  []
if [ ${a} -eq 10 -a ${b} -eq 50 ]; then
  echo "${a} -eq 10 -a ${b} -eq 50 :  return  true"
else
  echo "${a} -eq 10 -a ${b} -eq 50 :  return  false"
fi
# Output :10 -eq 10 -a 50 -eq 50 :  return  true

# double  []
if [[ ${a} -eq 10 && ${b} -eq 50 ]]; then
  echo "${a} -eq 10 && ${b} -eq 50 :  return  true"
else
  echo "${a} -eq 10 && ${b} -eq 50 :  return  false"
fi
# Output :10 -eq 10 && 50 -eq 50 :  return  true

if [ ${a} = ${b} ]
then
  echo "a  and  b  equal "
fi

if [ ${a} != ${b} ]
then
  echo "a  and  b  It's not equal "
fi
#a  and  b  It's not equal 

if [ -z ${x} ]; then
  echo "-z ${x}: String length is 0 "
else
  echo "-z ${x}: String length is not 0 "
fi
# Output :-z abc: String length is not 0

if [ -n ${y} ]; then
  echo "-z ${y}: String length is not 0 "
else
  echo "-z ${y}: String length is 0 "
fi
# Output :-z edf: String length is not 0

if [ $x ];then
  echo "${x}: Not an empty string "
else
  echo "${x}: Is an empty string "
fi
# Output :abc: Not an empty string 

if [ $s ];then
  echo '${s}: There is '
else
  echo '${s}: non-existent '
fi
# Output :${s}: non-existent 

File directory judgment operator

File directory judgment operator list

Operator explain
-f filename Judge whether the file exists , When filename When it exists and is a regular document ( It's not a catalog , It's not a device file ) return true
-d pathname Determine whether the directory exists , When pathname When it exists and returns a directory true
-e pathname Judge 【 Something 】 Whether there is , When pathname Returns when the specified file or directory exists true
-a pathname ditto , Outdated , And there's another logic to use with , Easy to confuse
-s filename Determine whether it is a non empty file , When filename Exists and the file size is greater than 0 When to return to true
-r pathname Judge whether it is readable , When pathname Returns when the specified file or directory exists and is readable true
-x pathname To judge whether or not to execute , When pathname Returns when the specified file or directory exists and is executable true
-w pathname Judge whether it is writable , When pathname Returns when the specified file or directory exists and is writable true
-b filename Determine whether it is a block file , When filename Returns when a block file exists true
-c filename Determine whether it is a character file , When filename When there is a character file, return true
-L filename Determine whether it is a symbolic link , When filename Return when there is a symbolic link true
-u filename Determine whether the file is set SUID position ,SUID yes Set User ID
-g filename Determine whether the file is set SGID position ,SGID yes Set Group ID

The sample code is as follows :

#!/bin/bash

file="/etc/hosts"

if [ -f ${file} ]; then
  echo "${file}: It's a common document "
else
  echo "${file}: It's not a normal file "
fi
# Output :/etc/hosts: It's a common document 

if [ -d ${file} ]; then
  echo "${file}: It's a catalog "
else
  echo "${file}: Not a directory "
fi
# Output :/etc/hosts: Not a directory 

if [ -e ${file} ]; then
  echo "${file}: File exists "
else
  echo "${file}: file does not exist "
fi
# Output :/etc/hosts: File exists 

if [ -s ${file} ]; then
  echo "${file}: The file is not empty "
else
  echo "${file}: The file is empty "
fi
# Output :/etc/hosts: The file is not empty 

if [ -r ${file} ]; then
  echo "${file}: Documents are readable "
else
  echo "${file}: The file is unreadable "
fi
# Output :/etc/hosts: Documents are readable 

Conditional statements

In a conditional statement , from [] or [[]] The wrapped expression is called Test command or Primitives .

if...fi sentence

 grammar :

if [ expression ]
then
  expression  yes  true , It's going to be enforced here 
fi
#!/bin/bash

if [ 1 = 1 ]
then
  echo " equal "
fi
# Output : equal 

# It can also be written in a line 
if [ "a" = "a" ]; then echo " equal "; fi
# Output : equal 

if...else Often follow test Command in combination with ,test The command is used to check if a condition holds , And square brackets [] similar ( The two of them are in /usr/bin It is pointed to by soft link ).

#!/bin/bash

a=10
b=50

if test ${a} -eq ${b}
then
  echo "a  be equal to  b"
else
  echo "a  It's not equal to  b"
fi
# Output :a  It's not equal to  b

if...else...fi

 grammar :

if [ expression ]
then
  expression  yes  true , It's going to be enforced here 
else
  expression  yes  false ,  It's going to be enforced here 
fi
#!/bin/bash

if [ 1 = 2 ]
then
  echo " equal "
else
  echo " It's not equal "
fi
# Output : It's not equal 

if...elif...fi

 grammar :

if [ expression1 ]
then
  expression  yes  true , It's going to be enforced here 
elif [ expression2 ]
then
  expression1  yes  true , It's going to be enforced here 
else
   above  expression  All are  false ,  It's going to be enforced here 
fi
#!/bin/bash

a=10
b=50

if [ ${a} -eq ${b} ]
then
  echo "a  be equal to  b"
elif [ ${a} -gt ${b} ]
then
  echo "a  Greater than  b"
else
  echo "a  Less than  b"
fi
# Output :a  Less than  b

case...esac

case...esac And in other languages switch...case similar , It's a multi branch selection structure .

case Statement matches a value or a pattern , If the match is successful , Execute the command you want to match . Applicable to many situations that need to be faced with , Different measures should be taken separately .

case  value  in
 Pattern 1)
  command1
  command2
  command3
  ;;
 Pattern 2)
  command1
  command2
  command3
  ;;
*)
  command1
  command2
  command3
  ;;
esac
#!/bin/bash

echo " Input 1-4 A number of "
echo " The number you entered is :"

read number

case $number in
  1)
  echo " You entered 1"
  ;;
  2)
  echo " You entered 2"
  ;;
  3)
  echo " You entered 3"
  ;;
  4)
  echo " You entered 4"
  ;;
  *)
  echo " What you input is not 1-4 The number of "
  ;;
esac

# After running, you can input digital experience by yourself 

Be careful : Can be in ) Pre use | Split multiple patterns .

Loop statement

bash There are four cycles in :for , while , until , select

for loop

 grammar :

for  Variable  in  list 
do
  command1
  command2
  ...
  commandN
done

A list in syntax is a set of values ( Numbers 、 character string ) The sequence of components , Each value is separated by a space . These values can also be wildcards or braces extensions , for example *.sh and {1..5}.

#!/bin/bash

for i in 1 2 3 4 5
do
  echo $i
done

#  Write in a line 
for i in {1..5}; do echo $i ; done

while loop

while The loop will constantly detect a condition , As long as this condition returns true, Just execute a command . The conditions to be tested are the same as if The same as in China .while It can also be used to read data from input files .

 grammar :

while [[ condition ]]
do
   If  condition  yes  true , The orders here will be executed 
done
#!/bin/bash

x=0
y=10

while [ ${x} -lt 5 ]
do
  echo $x
  x=`expr ${x} + 1`
done

# do  It's also written in a line with the conditions , You need a semicolon in front of it  ;
while [ ${y} -gt 5 ]; do echo $y; y=`expr ${y} - 1`; done

until loop

until The loop is to detect a condition , As long as the condition is false It's going to run the loop all the time , Until the condition is true Stop when . It goes with while Just the opposite .

#!/bin/bash

x=0

until [ ${x} -eq 5 ]; do
  echo ${x}
  x=`expr ${x} + 1`
done

select loop

select The syntax of loops follows for The cycle is basically the same . It helps us organize a user menu .

 grammar :

select  Variable  in  list 
do
   Execute the corresponding command 
done

select Will print the values of the list and their serial numbers to the screen , The user will then be prompted to choose , What users usually see is \$?, The user inputs the corresponding signal , The result of the selection will be saved to the variable .

#!/bin/bash

#PS3——shell Use in script select When the prompt 
PS3=" Select the package management tool you want to install , Enter the serial number :"

select ITEM in bower npm gem pip
do
  echo " The package name entered is :\c" && read PACKAGE
  case ${ITEM} in
    bower) echo " simulation  bower install ${PACKAGE}" ;;
    npm) echo " simulation  npm install ${PACKAGE}" ;;
    gem) echo " simulation  gem install ${PACKAGE}" ;;
    pip) echo " simulation  pip install ${PACKAGE}" ;;
    *) echo " Wrong selection of package management tool " ;;
  esac
  break # Out of the loop 
done

break command

break The command allows you to jump out of all loops ( Terminate all loops after execution ). In a nested loop break The command can also be followed by an integer , Jump out of a loop .

#!/bin/bash

#  When  x  be equal to  2, also  y  be equal to  0, Just jump out of the loop 
for x in 1 2 3
do
  for y in 0 5
  do
   if [ ${x} -eq 2 -a ${y} -eq 0 ]
   then
     echo "x  be equal to  ${x},y  be equal to  ${y}"
     break 2
   else
    echo "${x} ${y}"
   fi
  done
done

continue command

continue Command to break Command similar , There's only one difference , It doesn't jump out of all loops , Just jump out of the current loop . Again ,continue It can also be followed by a number , How many layers of loop to jump out of .

#!/bin/bash

#  When  x  be equal to  2, also  y  be equal to  0, Just jump out of the loop 
for x in 1 2 3
do
  for y in 0 5
  do
   if [ ${x} -eq 2 -a ${y} -eq 0 ]
   then
     continue 2
   else
    echo "${x} ${y}"
   fi
  done
done

function

  • shell Functions must be defined before they are used , Call a function using only its function name .
  • When a function is defined ,function Keywords are optional
  • Function return value : You can use it explicitly return sentence , Return value type can only be integer (0-255). If not return sentence , Will default to the last command run results as the return value .
  • Function return value after calling the function , adopt $? get .
 grammar : Brackets indicate optional 

[function] function_name () {
   Execute the command here 
  [return value]
}
#!/bin/bash

hello () {
  echo "hello"
  world # Nested function 
}

world () {
  echo "world"
}

hello

Parameters

Positional parameters are variables created when a function is called and passed its parameters , See above Shell Special variables .

#!/bin/bash

funWithParam () {
  echo " The first 1 Parameters :$1"
  echo " The first 2 Parameters :$2"
  echo " The first 3 Parameters :$3"
  echo " Wrong access to the first 10 Parameters :$10"
  # $10  Can't get No 10 Parameters , Need to use  ${10}, When  n>=10  when , Need to use  ${n}  To obtain parameters .( There's compatibility , some Shell The interpreter can get both )
  echo " Get it right 10 Parameters :${10}"
  echo " For the first 11 Parameters :${11}"
  echo " Get the number of transmitted parameters :$#"
  echo " Get all the parameters :$*"
  echo " The name of the current function is :$FUNCNAME"
}

funWithParam 1 2 3 4 5 6 7 8 9 34 73

I / O redirection

Unix Commands default from the standard input device (stdin) Get input , Output the results to the standard output device (stdout) Show . In general , The standard input device is the keyboard , The standard output device is the display .

I / O stream

shell Receives input , And produce output in the form of character sequence or character stream . These streams can be redirected to a file or to another stream .

In general , Every Unix/Linux The command will open three files : Standard input file 、 Standard output file 、 Standard error file , Three file descriptors :

Code The descriptor describe
0 stdin The standard input
1 stdout standard output
2 stderr Standard error output

Redirect

Redirection allows us to control where input to a command comes from , Where to output the results .

Output redirection : The output of a command can be more than just a display , You can also easily escape to files , This is called output redirection .

 grammar :

command > file   This syntax will override the contents of the file 

command >> file  If you don't want the file to be covered , have access to  >>  Append to end of file 

Input redirection : send Unix Command can also get input from file , In this way, the command to get input from the keyboard will be transferred to the file to read the content .

 grammar :
command < file

There is a document that test.sh, Output the number of lines in the file in two ways

wc -l ./test.sh
# Output :14 ./test.sh

wc -l < ./test.sh
# Output :14   No file name 

The first example will output the file name , The second one won't , Because it only knows what to read from standard input .

The following operators are used to control the redirection of flow :

The operator describe
> Redirect output
>> Redirect the output to the appended way
>& Merge two output files
<& Merge two input files
< Redirect input
<< Here Document Syntax ( See extension below ), Will start marking tag And closing marks tag Between the content as input
<<< Here character string

If you want to stderr Redirect to file, It can be written like this :

command 2 > file

If you want to stdout and stderr Redirected after merge file, It can be written like this :

#&[n]  Represents an existing file descriptor ,&1  For output  &2 Stands for error output  &- Represents closing the descriptor bound to it 
command > file 2 >&1

If you want to stdin and stdout All redirects , It can be written like this :

command < file1 > file2

# for example :
cat < test.sh  > catfile

# Mention it  <<  This is two small symbols in succession ,  He stands for 『 Ending input character 』 It means . So when the blank line is entered eof character , Input automatically ends , no need ctrl+D
cat <<eof >catfile

If you want to execute a command , But I don't want to display the output on the screen , So you can redirect the output to /dev/null.

/dev/null It's a special document , Everything written to it will be discarded , If you try to read from the file , So you can't read anything . however /dev/null Documents are very useful , Redirect the output of the command to it , It's going to work " No output " The effect of .

#test1.sh  Without it , Turn off the error output 
ls test.sh test1.sh 2>/dev/null

ls test.sh test1.sh 2>&-

# Turn off all outputs 
ls test.sh test1.sh  1>&- 2>&-
ls test.sh test1.sh  2>/dev/null 1>/dev/null

# Output the error 2  Bind to   Output correctly  1, And then   Output correctly   Send to  /dev/null equipment    This is commonly used 
ls test.sh test1.sh >/dev/null 2>&1
#&  For standard output  , Error output   All standard output and error output   Input to /dev/null file 
ls test.sh test1.sh &>/dev/null

Loading external scripts

Like any other language ,Shell You can also load external scripts , Merge the contents of the external script into the current script .shell There are two ways to write external scripts loaded in .

 The first one is :. filename

 The second kind :source filename

The two methods have the same effect , Simplicity , Generally, point numbers are used (.), however ! Note the number (.) And a space between the file name and

#!/bin/bash

. ./pre_test.sh

echo $a
#  Output :100

Debug

overall situation Debug

shell Provided for debug Tools for scripting . If you want to use debug Mode to run a script , Can be in its shebang Use a special option in the .( There are some shell I won't support it )

#!/bin/bash [options]

Or in execution Bash Script time , Pass in these parameters from the command line

bash -euxo pipefail test.sh

Local Debug

Sometimes we just need to debug Part of the script . In this case , Use set The command will be convenient . This command can enable or disable options . Use - Enable options , Use + Disable options .

1、 Used before running the results , First output the line of command executed

set -x
# perhaps 
set -o xtrace

2、 When executing a script , If you encounter a nonexistent variable, you will report an error , And stop executing .( The default is to ignore the error )

set  -u
# perhaps 
set  -o nounset

By the way , If the command line does not take any parameters , Direct operation set, All environment variables and Shell function .

3、 When executing a script , Terminate execution on error .( The default is to continue execution )

set  -e
# perhaps 
set -o errexit

# You can use the following method 
command || exit 1
# perhaps 
command1 && command2

set -e Judge according to the return value , Whether a command fails to run . however , The non-zero return value of some commands may not indicate a failure , Or the developer wants to have a command fail , The script goes on . It can be closed temporarily set -e, After the execution of the command , Open it again set -e.

set +e
command1
command2
set -e

# You can also use the following method 
command || true

4、 Pipeline command execution failed , The script terminates execution

A pipeline command is a number of subcommands through the pipeline operator (|) Combine it into one big command .Bash The return value of the last subcommand will be returned , As the return value of the entire command . The last subcommand does not fail , Pipeline commands always succeed , therefore set -e It will fail , Later orders will continue to be executed .

set -o pipefail To solve this situation , As long as one subcommand fails , The entire pipeline command will fail , The script will terminate execution .

set -eo pipefail

The commands above can be used together :

set -euxo pipefail
# perhaps 
set -eux
set -o pipefail

Expand

The script interpreter specifies... In the environment variable

In addition to the more common way of specifying script interpreter with path , Another is to specify the script interpreter in the environment variable .

 Specify the path to the script interpreter 
#!/bin/bash`

 Specifies the script interpreter in the environment variable 
#!/usr/bin/env bash

The advantage of this is , The system will automatically PATH Find the specified program in the environment variable ( As in the example bash). Because the path of the program is uncertain , For example, after installing the new version of bash after , We may add this new path to PATH in , Come on “ hide ” The old version of bash. So the operating system PATH Variables may be configured to point to another version of the program , If you still use it directly #!/bin/bash, Then the system will still choose the old version bash To execute the script , If you use #!/usr/bin/env bash, Will use the new version .

environment variable

All procedures , Include Shell The variables that can be accessed by the startup program at runtime are environment variables . stay shell Use in script export You can define environment variables , But only in the current running shell Effective in the process , The end of the process is gone . If you want to persist , Environment variables need to be defined in some column configuration files .

The loading order of the configuration file and shell Whether the process is running in Interactive and Login Patterns are about .

Interactive and non interactive patterns (Interactive & Non-Interactive)

  • Interactive Pattern : Usually refers to reading and writing data from the user's command line terminal (terminal), The user enters the command , And executed immediately after the return shell.
  • Non-Interactive Pattern : Usually refers to the execution of a shell Script , or bash -c Carry out orders

Detect current shell Is the running environment Interactive Pattern

[[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive"

Login and non login mode (Login & Non-Login)

  • Login Pattern : When the terminal logs in ,ssh When the connection ,su --login <username> When switching users , It refers to the user who has successfully logged in Shell process , This will read /etc/passwd The user belongs to shell perform .
  • Non-Login Pattern : Applications run directly bash when ,su <username> When switching users ( I didn't add --login). It refers to the state of non login user shell process .

Detect current shell Is the running environment Login Pattern

shopt -q login_shell && echo "Login shell" || echo "Not login shell"

# If it is zsh, No, shopt command 
[[ -o login ]] && echo "Login shell" || echo "Not login shell"

Get into bash It can also be used in interactive mode --login Parameter to determine whether it is login mode :

$> bash
$> shopt -q login_shell && echo "Login shell" || echo "Not login shell"
Not login shell
$> exit
$> bash --login
$> shopt -q login_shell && echo "Login shell" || echo "Not login shell"
Login shell
$> exit

Login In mode mode, you can use logout and exit sign out ,Non-Login In mode, you can only use exit sign out .

The configuration file ( Startup file ) Loading order

bash Supported profiles are /etc/profile、~/.bash.rc etc. .

As shown in the loading sequence above

  • Interactive&Login Pattern :/etc/profile —>( ~/.bash_profile, ~/.bash_login, ~/.profile) One of them —>~/.bash_loginout( sign out shell Called when the )
  • Interactive&Non-Login Pattern :/etc/bash.bashrc —>~/.bashrc
  • Non-Interactive Pattern : It's usually the execution of a script (script) When , In this case, the configuration items are read and executed from the environment variables , That is to say env perhaps printenv Configuration item for command output .

Today's systems generally don't have ~/.bash_profile The file , Only keep ~/.bashrc file , In all the systems ,~/.bash_profile There will be such logic , Avoid landing ~/.bashrc The situation of being skipped :

# login shell will execute this
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
        . "$HOME/.bashrc"
    fi
fi

In the release version of Linux In the system ,Interactive&Login Mode of ~/.bash_profile, ~/.bash_login, ~/.profile It doesn't have to be one of three , If you look at the contents of these three scripts, you will find that they will continue to call the next configuration file it wants to call , In this way, the configuration items may need to be configured multiple times in different configuration files . Such as centos7.2 in ~/.bash_profile The file actually calls ~/.bashrc file .

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

As shown in the figure above , To start a Shell Process time , The values of some parameters also affect the loading of configuration files . Such as --rcfile,--norc etc. .

frequently-used shell environment variable :

Variable name describe
PATH Command search path , Use colon as separator
HOME The pathname of the user's home directory , yes cd The default parameters of the command
SHELL Currently running Shell Full pathname of
TERM Terminal type
LOGNAME Current login name
PWD Current working directory
# Two ways to output individual environment variable values 

printenv HOME

echo $HOME

Global variables are variables that all users need to use , You can place new or modified variable settings in /etc/profile In file , But if you upgrade the distribution, the file will also be updated , So pay attention to this ( For all users ).

It's better to be in /etc/profile.d Create a directory to .sh Final document , Put all new or modified variables in this file ( For all users ).

For storage, individual users are permanent bash shell Where the variables are $HOME/.bashrc file . This applies to all types of shell process ( Only for current users ).

$* and $@ The difference between

$* and $@ Represents all parameters passed to a function or script , Not double quoted ("") Inclusion time , It's all about "$1" "$2" ... "\\$n" The form outputs all the parameters one by one .

But when they are enclosed in double quotation marks ,"$*" All parameters will be taken as a whole , With "$1 $2 ... $n" Output all parameters in the form of ."$@" It's the same as before , Separate all the parameters , One by one output .

for example :./test.sh a b c d


#/bin/bash

echo " Print out... Without quotation marks  $*"
for var in $*
do
echo "$var"
done
# Output : Print out... Without quotation marks  $*
# a
# b
# c
# d

echo " Print out quotation marks  \"$*\""
for var in "$*"
do
echo "$var"
done
# Output : Print out quotation marks  "$*"
# a b c d


echo " Print out... Without quotation marks  $@"
for var in $@
do
echo "$var"
done
# Output : Print out... Without quotation marks  $@
# a
# b
# c
# d

echo " Print out quotation marks  \"$@\""
for var in "$@"
do
echo "$var"
done
# Output : Print out quotation marks  "$@"
# a
# b
# c
# d

Shell Replace in

Escape character replacement

Use echo On command , Use -e You can replace the escape character . Use -E You can prohibit the escape of , Default is not escaped ; Use -n Option to disable the insertion of line breaks .

Escape character meaning
\b Backspace ( Delete key )
\f Change the page (FF), Move the current position to the beginning of the next page
\n Line break
\c Show no line breaks
\r enter
\t Horizontal tabs (tab key )
\v Vertical tabs

#/bin/bash

a=1
b=2

echo -e "${a}\n${b}" # Output :1

# 2

Command substitution

Command substitution means Shell You can execute the order first , Save the output temporarily , Output... In the right place .

The syntax of command substitution is : The quotation marks ``.


#!/bin/bash

DATE=`date`
echo " The date is :\$DATE" # Output : The date is :Sun Oct 18 16:27:42 CST 2020

() and (())

But first, let me say ()

stay bash in ,\$() And ``( The quotation marks ) They're used for command substitution . Complete the command line in quotes , Then replace the result with , And the new command line .

The same thing :\$() And `` In operation , Both of these are to achieve the corresponding effect

Difference :`` It's easy with '' Chaos , Especially for beginners , and \$( ) intuitive ; however \$() Compatibility issues , Some classes Unix The system does not support .

echo $(expr 1 + 2)

Besides, (())

1、(()) It can be directly used in integer calculation

echo $((1 + 2))

2、(()) Variable values can be redefined , Used to judge conditions or calculations, etc

#!/bin/bash

a=10
b=50

((a++))
echo $a
# Output :11

((a > b)) && echo "a > b"

((a < b)) && echo "a < b"

#  Output :a < b

3、(()) It can be used for base conversion

\$(()) You can convert other base numbers to decimal numbers and display them . grammar :$((N#xx)), among ,N In base ,xx Is a numeric value under the base , After the command is executed, you can get the decimal value of the decimal number .

echo $((2#110))
# Output :6
echo $((8#11))
# Output :9
echo $((16#1a))
# Output :26

test 、[] and [[]]

type Command check

type "test" "[" "[["
# Output :
#test is a shell builtin
#[ is a shell builtin
#[[ is a reserved word

As can be seen from the above ,test and [ Belong to Shell Built-in commands ,[[ Belong to Shell Reserved keywords for .

On the use ,test and [ It is equivalent. , Because it's an order , So you need to separate it from its parameters with spaces .

test -f /etc/hosts && echo True
# Output :True

[ -f /etc/hosts ] && echo True
# Output :True

because ] As the last parameter, it indicates the end of the condition , And like <> The symbol will be understood as redirection , Cause error

[ 1 < 2 ]
# Output :line 13: 2: No such file or directory

[[ Is the key word , Be able to understand the content according to the conventional semantics , The expression in double brackets is treated as a single statement , And return its status code .

[[ 1 < 2 ]] && echo True || echo False
# Output :True

Recommended [[ To make all kinds of judgments , Many mistakes can be avoided .

The following shows the errors caused by single brackets

[ $a == 1 && $b == 1 ] && echo True || echo False
# Output :[: missing `]'

# for example $a It's empty , Will report grammatical errors , because  [  What the order actually got was  ==、1、]  Three parameters 
[ $a == 1 ]
# Output :[: ==: unary operator expected

Here Document

Here Document It can be understood as “ The embedded document ”.Here Document yes Shell A special way of redirection , Its basic form is as follows :


command <<delimiter
document
delimiter

The function is to combine two delimiter Content between (document) Pass as input to command.

Be careful :

  • At the end of the delimiter Be sure to write at the top , There can't be any characters in front of it , There can't be any characters after it , Including spaces and tab Indent .
  • At the beginning delimiter Before and after the space will be ignored .
#!/bin/bash

wc -l << EOF
line 1
line 2
line 3
EOF # Output :3

Reference documents

版权声明
本文为[Fang Xu]所创,转载请带上原文链接,感谢

Scroll to Top