变量是shell传递数据的一种方法,变量是用来代替每个值的符号名。我们可以把变量当成一个容器,通过变量,可以在内存中存储数据。也可以在脚本执行中进行修改和访问存储的数据。
变量的设置规则- 变量名称通常是大写字母,它可以由数字、字母(大小写)和下划线组成。变量名区分大小写;但是不能以数字开头。
- 等号 = 用于为变量分配值,在使用过程中符号两边不能有空格。
- 变量存储的数据是整数数值和字符串值
- 在对变量赋予字符串值时,建议使用引号进行括起来,因为如果字符串中存在空格符号。需要使用单引号或双引号
- 要对变量进行调用,可以在变量名称前加美元符号$
- 如果需要增加变量的值,那么可以进行变量值的叠加,不过变量需要用双引号包含" 变 量 名 " 或 者 变量名"或者 变量名"或者{变量名}包含。
按照变量的作用可以分成4类:
- 用户定义变量
- 环境变量:这种变量主要保存的是和系统操作环境相关的数据。
- 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。
- 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。PATH
按照变量的作用域可以分成2类:全局变量和局部变量
- 局部变量是shell程序内部定义的,其使用的范围仅限于定义它的程序,对其他程序不可见。包括:用户自定义变量,位置变量和预定义变量。
- 全局变量是环境变量,其值不随shell脚本的执行结束而消失。
变量命名规则:由字母或下划线打头,不允许数字开头,后面由字母、数字或下划线组成,并且大小写字母意义不通,在使用变量时,在变量名前加$
[root@iz2zeb7b8tz2dr58b19mxrz opt]# VAR1=123
[root@iz2zeb7b8tz2dr58b19mxrz opt]# VAR1="123"
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo $VAR1
123
在看看错误的实例:
n a m e 是 name是 name是{name}的简化版本,但是在某些情况下,必须使用大括号括一下
[root@iz2zeb7b8tz2dr58b19mxrz opt]# VAR=mysql
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo $VAR
mysql
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo $VAR-db.log
mysql-db.log
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo $VAR.db.log
mysql.db.log
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo $VARdb.log
.log
[root@iz2zeb7b8tz2dr58b19mxrz opt]# ^C
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo ${VAR}db.log
mysqldb.log
我们对变量进行了追加,可以看到可以支持各种写法的追加,但是我们注意到最后两句echo $VARdb.log
和echo ${VAR}db.log
的打印结果,可以看到前者并不是我们想要的结果,因此这时候需要使用${}来进行操作了。
例如:在命令中调用date命令输出
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo `date`
Thu Apr 7 22:27:21 CST 2022
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo $(date)
Thu Apr 7 22:27:29 CST 2022
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo `date +%Y-%m-%d`
2022-04-07
命令的嵌套
使用的 ( ( (())
[root@iz2zeb7b8tz2dr58b19mxrz opt]# VAR=$(tar zcvf root.tar.gz $(find /root/ -name *.txt))
tar: Removing leading `/' from member names
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo $VAR
/root/jetty-distribution-9.2.26.v20180806/VERSION.txt
shell中单引号和双引号的区别
- 在单引号中所有的字符包括特殊字符($,‘’,`和\)都将解释成字符本身而称为普通字符
- 在双引号中,除了$,‘’,`和\以外所有的字符都将解释成字符本身,拥有“调用变量的值”、“引用命令”和“转义符”的特殊含义
注意:\转义符,跟在\之后的特殊字符将失去特殊含义,变量普通字符,如\ 将 输 出 " 将输出" 将输出""符号,而不是当做变量引用
单引号和双引号的使用场景
在给变量赋多个值的时候使用
[root@iz2zeb7b8tz2dr58b19mxrz ~]# clear
[root@iz2zeb7b8tz2dr58b19mxrz ~]# VAR=123 3214r
-bash: 3214r: command not found
[root@iz2zeb7b8tz2dr58b19mxrz ~]# VAR='123 3124r'
[root@iz2zeb7b8tz2dr58b19mxrz ~]# echo $VAR
123 3124r
单引号和双引号的区别
[root@iz2zeb7b8tz2dr58b19mxrz ~]# clear
[root@iz2zeb7b8tz2dr58b19mxrz ~]# VAR1='123'
[root@iz2zeb7b8tz2dr58b19mxrz ~]# VAR2='cc mk $VAR1'
[root@iz2zeb7b8tz2dr58b19mxrz ~]# VAR3="cc mk $VAR1"
[root@iz2zeb7b8tz2dr58b19mxrz ~]# echo $VAR2
cc mk $VAR1
[root@iz2zeb7b8tz2dr58b19mxrz ~]# echo $VAR3
cc mk 123
可以看到,单引号之间的内容原封不动给变量,双引号之间的内容如有特殊含义会保留的它的含义。
可以使用unset删除变量
unset VAR1
环境变量
在bash shell中,环境变量分为两类:全局变量和局部变量
全局变量:对于shell会话和所有的子shell都是课件的。
局部变量:它只在自己的进程当中使用。
局部变量#!/bin/bash
# this is shell
echo $VAR
我们在测试脚本中尝试输出变量
[root@iz2zeb7b8tz2dr58b19mxrz opt]# ./test.sh
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo $VAR
123
可以看到在test.sh
中是无法获取$VAR
的值的。
因为在在执行./test.sh
时候,会使用另一个bash去执行,就无法访问到$VAR的值。
env查看全局变量
env
我们在刚刚的test中尝试输出一下我们java的path路径
#!/bin/bash
# this is shell
echo $JAVA_PATH
[root@iz2zeb7b8tz2dr58b19mxrz opt]# ./test.sh
/opt/jdk/bin:/opt/jdk/jre/bin
再次执行发现可以获取到值。
使用export将局部变量变为全局变量[root@iz2zeb7b8tz2dr58b19mxrz opt]# VAR=1234
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo $VAR
1234
[root@iz2zeb7b8tz2dr58b19mxrz opt]# export VAR
[root@iz2zeb7b8tz2dr58b19mxrz opt]# vim test.sh
[root@iz2zeb7b8tz2dr58b19mxrz opt]# ./test.sh
1234
可以发现在使用export后在test中是可以获取到变量的值的。在里在使用env是可以查看到我们刚刚的VAR的
注意此时虽然我们将VAR设置成了全局变量,但是它还并不是永久生效的,例如我们重新开启一个shell连接的话,就无法获取到这个值
如果想让其永久生效,可以把定义好的变量写入配置文件。
当登录系统或开启一个ssh连接时候,一定会加载这4个配置文件:
vim /etc/profile #系统全局环境和登录系统的一些配置
vim /etc/bashrc #bash全局自定义配置文件,用于自定义shell
vim /root/.bashrc #单独自定义某个用户的bash
vim /root/.bash_profile #用户单独自定义某个用户的系统环境
那么我们是如何知道这个四个配置文件加载的先后顺序的呢?
可以每个文件的最后,追加一个echo命令输出一下文件的名字
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo 'echo /etc/profile' >> /etc/profile
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo 'echo /etc/bashrc' >> /etc/bashrc
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo 'echo /root/.bash_profile' >> /root/.bash_profile
[root@iz2zeb7b8tz2dr58b19mxrz opt]# echo 'echo /root/.bashrc' >> /root/.bashrc
然后我们在重新连接服务器可以看到如下:
这样我们就可以在/ect/profile下面添加永久的变量。例如我们在配置jdk的环境变量时候,就会在这里进行添加。
然后在执行 ./test.sh
[root@iz2zeb7b8tz2dr58b19mxrz opt]# source /etc/profile
[root@iz2zeb7b8tz2dr58b19mxrz opt]# ./test.sh
1234
发现可以输出了
那么如果我们在上述四个文件中都追加了VAR=1234.那么将会以执行顺序最后一个的变量为主,这里就不做演示了。
设置PATH环境变量SHELL要执行某一个程序,它要在系统中去搜索这个程序的路径,PATH变量是用来定义命令和查找命令的目录,当我们安装了第三方程序后,可以把第三方程序bin目录添加到path路径内,就可以在全局调用第三方程序。
例如我们的test.sh
在/opt目录下我们就只能在该目录下执行无法直接在任意目录执行test.sh
[root@iz2zeb7b8tz2dr58b19mxrz opt]# cd ~
[root@iz2zeb7b8tz2dr58b19mxrz ~]# test.sh
-bash: test.sh: command not found
我们来设置一下环境变量
vim /etc/profile
这里可以看看我们添加前后两次输出的echo $PATH
可以发现path是以:来进行分割,并且从前往后执行,因此我们如果想要我们的程序优先执行应该往前添加。
[root@iz2zeb7b8tz2dr58b19mxrz ~]# cd ~
[root@iz2zeb7b8tz2dr58b19mxrz ~]# source /etc/profile
/etc/profile
[root@iz2zeb7b8tz2dr58b19mxrz ~]# test.sh
1234
可以发现在任意目录都可以去执行test.sh
shell的位置变量shell解释执行用户的命令时,将命令的第一个字符作为命令名,而其他字符作为参数
$0
获取当前执行shell脚本的文件名,包括脚本路径,命令本身
$n
获取当前脚本的第n个参数 n=1、2…
我们来试一下,修改上述test.sh内容如下:
#!/bin/bash
# this is shell
echo "本shell脚本的文件名:$0"
echo "第1个参数:$1"
echo "第2个参数:$2"
echo "第3个参数:$3"
echo "第4个参数:$4"
执行如下
[root@iz2zeb7b8tz2dr58b19mxrz opt]# test.sh
本shell脚本的文件名:/opt/test.sh
第1个参数:
第2个参数:
第3个参数:
第4个参数:
[root@iz2zeb7b8tz2dr58b19mxrz opt]# test.sh 111 222 a.txt 444
本shell脚本的文件名:/opt/test.sh
第1个参数:111
第2个参数:222
第3个参数:a.txt
第4个参数:444
特殊变量
有些变量是一开始执行shell脚本时候就会设定,且不能被修改,但我们不叫他只读的系统变量而叫他特殊变量,这些变量当一执行程序时就有了,如下:
$*以一个单字符串显示所有向脚本传递的参数;如’$*'用【】括起来的情况,以$1 $2 3... 3... 3...n的形式输出所有参数$#传递到脚本的参数个数$$当前进程的进程号PID$?显示最后命令的退出状态;0表示没有错误,其他任何都表明有错误$!后台运行的最后一个进程的进程号pid测试一下:
vim test.sh
#!/bin/bash
# this is shell
echo "本shell脚本的文件名:$0"
echo "第1个参数:$1"
echo "第2个参数:$2"
echo "第3个参数:$3"
echo "第4个参数:$4"
echo '【$*】' "【$*】"
echo '$# '"$#"
echo '$$ '"$$"
echo '$? '"$?"
echo '$! '"$!"
执行如下:
[root@iz2zeb7b8tz2dr58b19mxrz opt]# test.sh 111 222 a.txt 444
本shell脚本的文件名:/opt/test.sh
第1个参数:111
第2个参数:222
第3个参数:a.txt
第4个参数:444
【$*】 【111 222 a.txt 444】
$# 4
$$ 22341
$? 0
$!