Shell - variables and how the script runs

variable

In other programming languages, for example, C language variables have multiple types: integer, floating point, character, logical, etc.

But variables in the shell一切皆为字符串


Several ways to define variables

When the shell assigns a value to a variable, there must be no spaces on the left and right sides of =, for example, a=1 means the assignment relationship, and if it is written as a = 1, it means the equivalence relationship test

1) No quotes

  • parse special symbols
  • Unable to parse special command
  • Can't enter a space
age=18

2) Single quotes

  • Do not parse all special symbols and commands
  • spaces can be entered
  • what you see is what you get
name='echo zhang san'

3) Double quotes

  • parse special symbols
  • Unable to parse special command
  • spaces can be entered
phone_num="123 456"

4) Backticks

  • parse special symbols
  • parse special commands
  • spaces can be entered
a='echo hello world!'
b=`${
     
     a}`
echo ${b}

The above code will eventually output hello world!, the process is divided into 2 steps:

  • The special symbol ${a} is parsed, and the string stored in a is taken out
  • Find that the string is a special command, then parse the string, and finally assign the printed result to b

Variable scope and export and local

The variable is created in the current bash environment . If it is not deleted, its scope is the creation location --> the end of the current bash environment , and it can be accessed in 终端, 脚本and . 函数Variable scope needs to understand the relationship between parent and child shells, which is in the last section.

1)export

If the variable a is created in the current bash environment, it will not be recognized after entering the sub-bash.

For this situation, variables can exportbe modified, and exportthe modified variables can 子bashbe accessed in the environment.

For example, enter the following command at the command end:

[root@learning ~] a=1
[root@learning ~] echo 'echo "${a}"' > print_a.sh
[root@learning ~] bash print_a.sh
                #无法访问变量a,打印出空值
[root@learning ~] export a
[root@learning ~] bash print_a.sh
1               #打印结果为1,说明export定义的变量子bash可以访问

In the above code:

  • Running a script in bash opens up a child bash environment that doesn't have access to variables defined in the parent bash
  • Add export in front of the variable for modification, and you can access the variable; export can be modified when the variable is declared, and it can be modified after the declaration

Note: The variables defined by export are only useful to the child bash, and the modification of the variable by the child bash will not affect the parent bash, but only affect the value of the variable in the current bash environment

[root@learning ~] export a=1
[root@learning ~] bash  #进入一个子bash环境
[root@learning ~] export a=2
[root@learning ~] bash
[root@learning ~] echo $a
2
[root@learning ~] exit  #退出当前bash环境
exit
[root@learning ~] exit
exit
[root@learning ~] echo $a
1

The above example is obvious:

  • Variables defined by the parent bash with export can be accessed by the child bash
  • The value of the variable changed by the child bash cannot affect the parent bash
  • The relationship between variables in the parent-child bash environment is a temporary copy of the variable, similar to the call by value of a function in C language.

Note: export is also useful for functions

2)loacl

In a function, if you do not want the variable to be accessed outside the function, you can loaclmodify the variable in the function as follows:

#函数中不加loacl
$ cat > hello.sh << "EOF"
#!/bin/bash
function hello()
{
   print=hello
 }
hello      #运行函数
EOF
echo $print
hello

#函数中加local
cat > hello.sh << "EOF"
#!/bin/bash
function hello()
{
   local print=hello
}
hello
EOF
echo $print
                    #打印不出来print的值

Obviously:

  • The variables normally created in the function, after the function runs, the terminal can access the value of the variable
  • The variable modified with loacl in the function, after the function runs, the terminal cannot access the value of the variable

Variable extraction, modification and deletion

1) Extraction of variables

The format of variable extraction is as follows:

name="变量名"
${name}  #推荐使用该方法
$name

Among the above methods, in order to reduce bugs and increase the readability of the code, it is recommended to use the ${} method.

2) Modification of variables

Variable modification can be completed by directly reassigning the variable

name="zhangsan"
name="lishi"

3) Deletion of variables

Use the unset command to delete specified variables. unset supports deleting multiple variables at a time; if there are a series of variables with the same characteristics, you can use set | grep to search for variables, and then delete them according to the search results

name1="zhangsan"
name2="lisi"
name3="wangwu"
set | grep "^name"

Among them: setmeans to find all variables, including system variables, |means pipeline, gerp “^name”means to find variables starting with name

The result of the operation is as follows:

name1=zhangsan
name2=lisi
name3=wangwu

Then you can delete the variable by unset

unset name1 name2 name3

special variable

Special variables also follow the basic syntax of variable extraction, that is, ${}; for the convenience of writing, the following codes are abbreviated.

1) Positional parameters

In linux, when executing a command or script, multiple parameters can be entered later, and these parameters are collectively referred to as positional parameters; where ${0} represents the executed command or script, ${1} represents the first positional parameter, and ${2 } Indicates the second positional parameter, in turn.

Write a script pos_param.sh

#!/bin/bash
echo "执行的脚本或命令是${0}"
echo "第一个位置参数是${1}"
echo "第二个位置参数是${2}"
echo "第三个位置参数是${3}"
echo "第四个位置参数是${4}"
echo "第五个位置参数是${5}"

run script

bash pos_param.sh 1111 2222 3333 4444 5555

The result is as follows

The executed script or command is pos_param.sh
The first positional parameter is 1111
The second positional parameter is 2222
The third positional parameter is 3333
The fourth positional parameter is 4444
The fifth positional parameter is 5555

Note: When the number of positional parameters is less than 10, {} can be omitted, for example: $0, $1, $2, etc.; while the positional parameters of more than 10 must be in the form of ${}, for example: ${10}, ${ 11} etc.


Positional Arguments Exercise: Creating a New User

cat > makeuser.sh << "EOF"
#!bin/bash
useradd ${1}
echo "${2}" | passwd --stdin ${1}
EOF
bash makeuser.sh lisi 1234

Note: This method of modifying user passwords is not applicable to ubuntu

The running results will report the following prompts:

Changing password for user lisi.
passwd: all authentication tokens updated successfully.

2) ${#} gets the number of incoming parameters

echo 'echo "共传入$#个参数"' >> pos_param.sh 

bash pos_param.sh 1111 2222 3333 4444 5555

On the basis of 1), continue to add the following commands to the script, run the command in 1) again to execute the script, and the following will be printed:

A total of 5 parameters are passed in

Obviously, $# will get the number of all parameters in the incoming script.

3) ${$} gets the current process ID

Continue to add the following commands:

echo 'echo "当前进程ID是$$"' >> pos_param.sh 

bash pos_param.sh 1111 2222 3333 4444 5555

Under the print content:

The current process ID is 14109

14109 is the process ID number of pos_param.sh

4) ${*} and ${@} receive all parameters

Both ${*} and ${@} receive all parameters, but they are slightly different

Execute the following code:

cat >> pos_param.sh << "EOF"
echo "\$*接收的参数为:$*" 
echo "\$@接收的参数为:$@" 

echo "用for循环打印\$*接收的参数为:"
count=0;
for a in "$*"
do 
let count++ 
echo "第${count}个位置参数是:${a}"
done

echo "用for循环打印\$@接收的参数为:"
count=0;
for b in "$@"
do 
let count++ 
echo "第${count}个位置参数是:${b}"
done
EOF

bash pos_param.sh 111 222 333 

The result of the operation is as follows:

$*Received parameters are: 111 222 333
$@Received parameters are: 111 222 333
Use for loop to print $* Received parameters are:
The first position parameter is: 111 222 333
Use for loop to print $@Received parameters For:
The first positional parameter is: 111
The second positional parameter is: 222
The third positional parameter is: 333

Obviously : both can receive incoming parameters

  • ${*} stores all parameters as a string and cannot be separated
  • ${@} is to store all parameters separately

5) ${?} Get the execution result of the last command

In writing code at ordinary times, such as C language: We often use the return value to judge whether the running result of a certain function or program is correct, and the same is true in shell scripts

In the shell, if the return value is 0, it means that the operation is correct, and if it is not 0, it means that there is an error

For example:

[wjj@why1472587 ~]$ ls 777
ls: cannot access 777: No such file or directory
[wjj@why1472587 ~]$ echo $?
2
[wjj@why1472587 ~]$ ls
study
[wjj@why1472587 ~]$ echo $?
0

6) $() to get the command

The content in $() ()is no longer treated as a variable, but as a command.

For example: whoamithe current user can be viewed through the command, which can be used as follows:

echo "当前用户:$(whoami)"

Two Execution Methods of Shell Script

First write a Hello World!script that prints

cat > test1.sh << 'EOF' 
#!/bin/bash
echo "Hello World!"
EOF

1) Add execution permission to run

chmod u+x test1.sh
./test1.sh

2) No need to execute permissions, run as an interpreter

  • to bashrun
  • to sourcerun
  • to .run (requires a shebang at the beginning of the file)
#1
bash test1.sh
#2
source test1.sh
#3
. tesh1.sh #文件开头需要有shebang

1. The difference between bash, source and .run

  • When using sourceand .running, it is running in the current bash environment
  • When using bashthe runtime, an additional sub-bash environment will be created

Use the pstree -p command to open the process running on the current linux system and view the PID process number

1) Run as sourceand .:

insert image description here

2) to bashrun:

insert image description here

After the script finishes running, it will exit the current sub-bash environment

2. What is a shebang

shebang is a line of text, placed on the first line of the shell script, telling the computer what interpreter the current script uses to run

#!/bin/bash

Among them, #!it means that this is a shebang, /bin/bashand it is the path of the interpreter.

The above shebang indicates that the script runs with a bash interpreter; if it is a python script, it needs to be changed to:

#!/bin/python

As interpreted languages, shell and python can run scripts directly with the interpreter by adding shebang; while other compiled languages, such as C/C++, Java, etc. need to be compiled before running, and the environment required for compilation needs to be installed .

If no shebang is declared in the first line of the script, the system will run the script in the current bash environment by default.


constant

The C language can make variables have constant attributes by #define defining constants, or by modifying variables into constant variables.const

However, the shell does not strictly distinguish between constants and variables. Generally speaking, variables that meet the following two points are used as constants:

  • Name variables in pure uppercase (conventional way of definition)
  • By readonlysetting the variable as read-only, it cannot be changed

For example:

[wjj@learning ~]$ readonly MAX_READ=100
[wjj@learning ~]$ echo $MAX_READ
100
[wjj@learning ~]$ MAX_READ=200
-bash: MAX_READ: readonly variable

As above: If the variable is set to read-only through readonly, an error will be reported when reassigning the read-only variable readonly variable.

Note: unsetThe command cannot delete read-only variables, and there is no way to delete read-only variables in bash. When exiting the bash environment, all variables created are automatically destroyed.

Guess you like

Origin blog.csdn.net/why1472587/article/details/128511552