定义变量的规则
在定义变量时,有一些规则需要遵守:
变量名称可以由字母、数字和下划线组成,但不能以数字开头;
在 Bash 中,变量的默认类型都是字符串,如果要进行数值运算,则必须指定变量类型为数值型;
变量用等号连接值,等号左右两侧不能有空格。例如:
1
2[root@localhost ~]# name = cangls
-bash: name: command not found变量的值如果有空格,需要使用单引号或者双引号括起来。 如:
test="hello world"
。其中双引号括起来的内容$
、\
和反引号都拥有特殊含义,而但因好括起来的内容都是普通字符。在变量的值中,可以使用
\
转义符。如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要双引号包括
"$变量名"
或者使用"${变量名}"
来包含变量名。例如:1
2
3
4
5
6
7
8
9#叠加变量 test,变量值变成了123456
[root@localhost ~ ] # test=123
[root@localhost ~ ] # test="$test"456
[root@localhost ~ ] # echo $test
123456
#再叠加变量 test,变量值变成了123456789
[root@localhost ~ ] # test=${test}789
[root@localhost ~ ] # echo $test
123456789如果是把命令的结果作为变量值赋予变量,则需要使用反引号或者
$( )
包含命令。例如:1
2
3[root@localhost ~ ] # test=$(date)
[root@localhost ~ ] # echo $test
2022年 10月 28日 星期五 16:29:16 CST
变量的分类
在Shell中变量的分类:
类型 | 描述 |
---|---|
用户自定义变量 | 这种变量是最常见的变量,由用户自由定义变量名和变量值。(只在当前Shell生效,子Shell不生效) |
环境变量 | 这种变量中主要保存的是和系统操作环境相关的数据,比如当前登录用户,用户的家目录,命令的提示符等。环境变量的变量名可以自由定义,但是一般对系统起作用的环境变量的变量名是系统预先设定好的。 |
预定义变量 | 在Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的 |
位置参数变量 | 主要用来向脚本传递参数或数据的,变量名不能自定义,作用是固定的 |
1 | 说明:环境变量分为两种,一种是允许用户自定义的,还有一种是系统定义好的。 |
用户自定义变量
这种变量是最常见的变量,由用户自由定义变量名和变量值。
可以在Shell 脚本里面定义,也可以在终端里面直接定义
1 | [root@localhost ~ ] # test=123 |
环境变量
在Shell中,环境变量分为两种。一种时用户自定义的环境变量,另一种是系统自带的环境变量。
查看环境变量时使用 env
命令去查询。
用户自定义的环境变量
使用 export
关键字声明的变量就是环境变量。
1 | [root@localhost ~]# export AGE="18" |
也可以先定义一个自定义变量,然后把自定义变量声明为环境变量:
1 | [root@localhost ~]# AGE=18 |
系统自带的环境变量
系统自带的环境变量名称和作用都不能改变,这里只介绍一个 PATH
环境变量。
PATH环境变量的作用是系统查找命令的路径。
在执行脚本时可以通过绝对路径去执行,也可以通过相对路径执行。这两种都可以理解,因为都能精准的通过路径找到该脚本,或者当前目录就有该脚本。
有一些系统命令,比如 ls
,ls
命令在系统的 /bin
目录下。但我们直接执行 ls
命令,并没有使用绝对路径,系统就能执行 ls
命令,这是为什么呢?
根本原因就是在这个 PATH 环境变量中。
PATH环境变量中配置的这些路径,就是系统查找命令的路径。也就是说当我们输入了一个程序名,如果没有写命令的路径,系统就会到PATH环境变量定义的路径中去寻找,是否有可以执行的程序。从左到右一个一个目录查找你所要执行的命令,找到了就直接执行,而如果把所有的目录都搜索完了,也没有找到你所执行的命令,就会报错,提示:
1 | bash: tttt:未找到命令 |
那想要不输入绝对路径就能执行一个程序或者脚本,就只要对PATH环境变量进行叠加就可以实现了
1 | #在变量PATH的后面,加入/root/sh目录 |
但需要注意的是,这种方法只是临时生活笑,一旦重启或者注销就会消失。如果想要永久生效,就需要写入环境变量配置文件 /etc/profile
中。比如配置JAVA环境
1 | ## 假设JAVA环境已经解压好了 |
想要环境变量生效需要重启或者注销,但也可以让当前Shell生效,使用以下命令:
1 | [root@localhost ~]# source /etc/profile |
预定义变量
预定义变量就是,事先把变量的名称和作用确定好(都是不可变的),只能修改变量的内容,也就是变量的值。
其实预定义变量和位置参数变量都可以统称为预定义变量。
预定义变量 | 作用 |
---|---|
$? |
$? 存储的值是最后一次执行的命令的返回状态。 |
$$ |
当前进程的进程号(PID) |
$! |
后台允许的最后一个进程的进程号(PID) |
1 | 在 `$?` 的返回状态中,变量值为0则代表上一个命令正确执行;变量值非0则代表上一个命令执行不正确。 |
位置参数变量
位置参数变量的作用主要用于脚本的传参。
位置变量参数 | 作用 |
---|---|
$n |
n 为数字,$0 代表命令本身,$1-$9 代表第一个到第九个参数,十个以上的参数需要用大括号括起来:${10} |
$* |
这个变量代表命令行中所有的参数,$* 把所有的参数看成一个整体 |
$@ |
这个变量也代表命令行中所有的参数,不过 $@ 把每个参数区分对待 |
$# |
这个变量代表命令行中所有参数的个数 |
$n
n 为数字,$n
代表命令本身
1 | [root@localhost ~]# bash add.sh 1 2 |
在以上示例中,$0
代表命令本身,$1
为1,$2
为2,以此类推。
$#$#
这个变量代表命令行中所有参数的个数
1 | # 定义一个脚本parameter.sh |
变量的作用域
Shell 脚本中所产生的变量默认情况下只针对当前终端或者当前 Shell 生效的,那如果在当前 Shell 中生成一个新的子 Shell、或者是该 Shell 的父进程,都无法引用当前 Shell 下创建的变量。
1 | 那如何将当前 Shell 创建的变量能在父 Shell 或者子 Shell 中运行呢? |
可以更改执行脚本的方式,也可以将该变量导出
改变执行脚本的方式
Shell 脚本的执行脚本方式有4中,分别是:
- bash demo.sh
- ./demo.sh
- source demo.sh
- . demo.sh
1 | 这 4 种方式分别有什么区别呢? |
bash demo.sh 和 ./demo.sh 这两种方式很类似,这两种方式会产生一个叫做 bash
的子进程,在这个子进程下面再去运行该脚本。唯一的区别呢就是 ./demo.sh 的这种方式会执行 Sha-Bang
,而 bash 不用,因为这种方式就显示的指定 bash 去执行该脚本。
而后两种方式 source demo.sh 和 . demo.sh 就和前 2 种产生子进程然后执行脚本的方式不一样,这两种是在本进程下面去执行脚本文件的。
示例:
1 | ## 创建一个脚本文件,文件含义就是进入 /etc 目录下,并且打印出当前目录的路径 |
所以要想在子 Shell 去引用父 Shell 的变量,那就要使用 source
和 .
的方式去执行脚本
导出变量
另外一种方式就是将该变量设置为导出
1 | export 变量名=值 |
将该变量导出之后,就可以在子 Shell 中使用父 Shell 中导出的变量。
接收键盘输入的数据
位置参数变量是用来向脚本中传递值的,但在执行脚本的时候,脚本无法给出所需参数的提示,这是对用户非常的不友好。
这种情况下可以使用 read
命令去解决,read
命令是用来接受键盘输入的命令,并提示相关输入说明。
命令格式如下:
1 | read [选项] [变量名] |
选项:
- -p:“提示信息”:在等待read输入时,输出提示信息。
- -t:秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间。
- -n:字符数:read命令只接受指定的字符数,就会执行。
- -s:隐藏输入的数据,适用于机密信息的输入。
变量名:
- 变量名可以自定义,如果不指定变量名,会把输入保存入默认变量REPLY。
- 如果只提供了一个变量名,则整个输入行赋予该变量。
- 如果提供了一个以上的变量名,则输入行分为若干字,一个接一个地赋予各个变量,而命令行上的最后一个变量取得剩余的所有字。
示例:
1 | # 定义一个shell脚本read.sh。 |
最后赋予执行权限并运行:
1 | chmod +x read.sh |