变量名命名规则
1.名称定义要见名之意,按照规则来,不得引用保留关键字(help检查保留字)
2.只能包含数字、字母、下划线
3.不能以数字开头
4.不能用标点符号
5.变量名严格区分大小写
有效的变量名:
NAME_DATA
_change
_change1
chAoE1
无效的变量名
?change
chao*ge
变量的作用域
本地变量:只针对当前的shell进程,切换shell 变量会丢失
环境变量:也称为全局变量,针对当前shell以及其任意子进程,环境变量也分自定义、内置两种环境变量
局部变量:针对在shell函数或者shell脚本中定义的
位置参数变量:用于shell脚本中传递的参数
特殊变量:shell内置的特殊功效变量
$?
返回值0:成功
返回这1-255:错误码
一般在shell脚本中用于上一条命令是否执行成功
自定义变量:name=value
变量引用:${name}、$name
双引号,变量名会替换为变量值
例如:在shell环境中
我们自定义变量 n1=1 n2=2
这个时候我们使用n3="$n1"
我们打印n3 命令:echo $n3 结果也是1,这句话就是"$n1"其实是获取的n1的值,我们将这个值赋值给了n3,所以直接打印n3的值也是1
但是如果我们使用单引号n4='$n2',那么我们打印的结果则是$n2,不会进行替换
注意本地变量,当前shell:
单引号变量,不识别特殊语法
双引号变量,能识别特殊语法
无引号,连续的符号可以不加引号
反引号,引用命令执行结果,等于$()用法
如下:
[root@VM-28-7-centos ~]# name="lsz"
[root@VM-28-7-centos ~]# n1='${name}'
[root@VM-28-7-centos ~]# echo n1
${name}
# 在上述中,我们使用${name}是特殊语法可以取出name的值,但是单引号并没有识别出来,我们打印n1的值为${name}[root@VM-28-7-centos ~]# n2="${name}"
[root@VM-28-7-centos ~]# echo $n2
lsz
我们使用了双引号,那么就会识别特殊语法
关于shell的执行作用域:
1.每次调用bash/sh 解释器执行脚本,都会开启一个子shell,因此不保留当前的shell变量,通过pstree命令可以检查进程树
2.调用source或者点符号是在当前shell环境加载脚本,因此会保留变量
# 演示
1.开启子shell的执行方式
[root@VM-28-7-centos ~]# vim book.sh
[root@VM-28-7-centos ~]# cat book.sh
#!/bin/bash
name="大西瓜"
[root@VM-28-7-centos ~]# name="小西瓜"
[root@VM-28-7-centos ~]# echo $name
小西瓜
[root@VM-28-7-centos ~]# sh book.sh
[root@VM-28-7-centos ~]# echo $name
小西瓜
# 我们定义了一个book.sh,里面写入了一个变量名,当我们执行了sh文件后,他会开启子shell执行sh脚本,因此我们在当前shell的环境中name的值没有发生改变
2.不开启子shell的执行方式
[root@VM-28-7-centos ~]# source book.sh
[root@VM-28-7-centos ~]# echo $name
大西瓜
# 我们使用了source 执行sh脚本就不会开启子shell执行,使用的当前shell解释器,就会将当前已经定义的name值进行改变
环境变量
环境变量一般指的是export内置命令导出的变量,用于定义shell的运行环境,保证shell命令的正确性
shell通过环境变量确定登录的用户名、PATH路径、文件系统等各种应用
环境变量可以在命令行中临时创建,但是用户退出shell终端,变量即丢失,如果想要永久生效,需要修改环境变量配置文件
* 用户个人配置文件:~/.bash_profile 、~/.bashrc 远程登录用户特有文件
* 全局配置文件 /ect/profile 、 /etc/bashrc ,切系统建议最好创建在/etc/profile.d/ 而非直接修改主文件,修改全局配置文件,影响所有登录系统的用户
检查系统环境变量的命令
1.set,输出所有变量,包括全局变量/局部变量
2.env 只显示全局变量
3.declare 输出所有的变量,如同set
4.ecport 现实和设置环境变量值
撤销环境变量
unset 变量名 删除变量或函数
设置只读变量
readonly 只有shell结束,只读变量失效
特殊参数变量
$0 获取shell脚本文件名,以及脚本路径
$n 获取shell脚本的第n个参数,n在1-9之间
$# 获取执行的shell脚本后面的参数总个数
$* 获取shell脚本所有参数,不加引号等同于$@作用,加上引号"$*"作用
$@ 不加引号,效果同上,加引号,是接受所有参数为独立字符串,如"$1" "$2" ,空格保留
$*与$@ 的区别:
$*会将所有的参数从整体上看做是一份数据,而不是把每个参数都看做一份数据,按照python中的理解可以理解为他将所有的参数放到了同一个字符串里面
$@会将每个参数都看做一份数据,彼此直接是独立的,按照python的理解可以理解为他输出了多个字符串,每个字符串是一个参数
如下所示:
[root@VM-28-7-centos ~]# cat book.sh
#!/bin/bash
echo "print echo param from \"\$*\""
# 这里是一个for循环
for var in "$*"
do
echo "$var"
done
echo "print echo param from \"\$@\""
for var in "$@"
do
echo "$var"
done
[root@VM-28-7-centos ~]# bash book.sh 11 12 13 14
print echo param from "$*"
11 12 13 14
print echo param from "$@"
11
12
13
14
# 使用for循环我们就可以看出来两者的区别
特殊状态变量
$? 上一次命令执行状态返回值,0正确,非0失败
$$ 当前shell脚本的进程号
$! 上一次后台进行的PID
$_ 再次之前执行的命令,最后一个参数
查找方式 man bash
搜索Special Parameters
shell子串
bash一些基础的内置命令
echo:打印输出
eval:执行多个命令
exec:不创建子进程,执行后续命令,并且执行完毕,自动exit
export:
read
shift
echo
-n:不换行输出
-e:解析字符串中的特殊符号
\n 换行
\r 回车
\t 制表符 4个空格
\b 退格
shell子串的花式语法
字符串截取
${变量}: 返回变量值
${#变量}: 返回变量长度,字符长度
${变量:start} 返回变量start数值之后的的字符
${变量:start:length} 提供start之后的length限制的字符
${变量#word} 从变量开头删除最短匹配的word子串
${变量##word} 从变量开头,删除最长匹配的word
${变量%word} 从变量结尾删除最短的word
${变量%%word} 从变量结尾开始删除最长匹配的word
${变量/pattern/string} 用string代替第一个匹配的pattern
${变量//pettern/string} 用string替代所有的pattern
[root@VM-28-7-centos ~]# echo $name
大西瓜
[root@VM-28-7-centos ~]# echo ${#name}
3
[root@VM-28-7-centos ~]# echo ${name:2}
瓜
[root@VM-28-7-centos ~]# echo ${name:1:1}
西
[root@VM-28-7-centos ~]# echo ${name#大}
西瓜
[root@VM-28-7-centos ~]# name="yuchao"
[root@VM-28-7-centos ~]# echo ${name#yu}
chao
[root@VM-28-7-centos ~]# echo ${name/yu/zh}
zhchao
# 可以理解为python的字符串操作,
${#name}代表是len,${name#大}切割,split,
${name/yu/zh}替换replace,
{name:1:1}从索引1开始截取截取长度为1
# 注意这些操作并不会影响字符串本身
[root@VM-28-7-centos ~]# echo ${name/yu/zh}
zhchao
[root@VM-28-7-centos ~]# echo $name
yuchao
案例:批量替换文件名
[root@VM-28-7-centos ~]# ls
book_one_fin.sh book_three_fin.sh book_two_fin.sh demo.text mysql57-community-release-el7-10.noarch.rpm
[root@VM-28-7-centos ~]# vim udapte_file_name.sh
[root@VM-28-7-centos ~]# bash udapte_file_name.sh
[root@VM-28-7-centos ~]# ls
book_one.sh book_three.sh book_two.sh demo.text mysql57-community-release-el7-10.noarch.rpm udapte_file_name.sh
[root@VM-28-7-centos ~]# cat udapte_file_name.sh
#!/bin/bash/
# 获取所有fin结尾的文件名
ls_result=`ls *fin.sh`
for result in $ls_result
do
mv $result ${result//_fin/}
done
# 我们在sh文件中首先获取ls 命令的执行结果,然后进行for,按照字符串的操作进行批量替换,对于python来说就是os获取所有名字然后使用rename就可以了
特殊shell拓展变量
变量的处理
如果parameter变量值为空,返回word字符串
${parameter:-word}
如果para变量为空,则word代替变量值,且返回其值
${parameter:=word}
如果para变量为空,word当做stderr输出,否则输出变量值
用于设置变量为空导致错误时,返回的错误信息
${parameter:?word}
如果para变量为空,什么都不做,否则word返回
${parameter:+word}
内置命令、外置命令
内置命令:在系统启动时就会加载入内存,常驻内存,执行效率更高,但是占用资源
外置命令:用户需要从硬盘中读取程序文件,再读入内存加载
执行脚本的方式
source
. test.sh
bash test.sh
./test.sh # 这样的方式需要添加可执行权限
sh ./test.sh
Shell运算
用于数值计算的命令
双小括号
[root@VM-28-7-centos ~]# cat test.sh
#!/bin/bash
i=2
((i=i+1))
echo $i
[root@VM-28-7-centos ~]# sh test.sh
3
上面就是简单用法,其实就跟我们python是差不多的,就是python可以直接用I=I+1,然后直接print变量名,shell需要用$才能取出来变量的值
简单逻辑运算
[root@VM-28-7-centos ~]# echo $((6>7))
0
[root@VM-28-7-centos ~]# echo $((6<7))
1
# 可以理解为python的True或者False,如果为真则为True也就是1,如果为假则为False就是0
复杂逻辑运算
[root@VM-28-7-centos ~]# echo $((6<7&&2>3))
0
[root@VM-28-7-centos ~]# echo $((6<7&&2<3))
1
# &&表示两边都成立则为1,如果有一边不成立则为0,相当于python的and
[root@VM-28-7-centos ~]# echo $((6<7||2<3))
1
# || 或的意思,只要符号两边有一个成立则就为1,相当于python的or
基本运算
[root@VM-28-7-centos ~]# cat test.sh
#!/bin/bash
# 加法
echo $((3+4))
# 减法
echo $((4-3))
# 乘法
echo $((3*4))
# 除法
echo $((10/3))
# 取余
echo $((10%3))
[root@VM-28-7-centos ~]# sh test.sh
7
1
12
3
1
# 上面基本运算符,$的作用是取值,需要记得就是除法,/是用来或者商的,%用来获取余数
特殊符号运算
++ +1
-- -1
坑:
++a,先计算+1,然后在赋值给a
a++,先对变量a进行操作再进行+1
示例:
[root@VM-28-7-centos ~]# cat test.sh
#!/bin/basha=1
((a++))
echo $a
b=1
echo $((b++))
echo $b[root@VM-28-7-centos ~]# sh test.sh
2
1
2
我们分别进行了3次打印,a++很好理解直接+1然后赋值给了a,a本来是1,然后加1就是2,echo $((b++)) 他是首先打印b,然后再计算,所以打印初始的b是1
echo $b 我们再对b进行取值,那他获取就是b+1以后的
简单的数字脚本
#!/bin/bash
read -p "请输入你的数字" number
if [ $number>10 ]
then
echo "你输入的数字大于10了"
fi
# 这里用到了read -p 表示代码走到这里会让用户输入一个数字并赋值给number这个变量
# if 后面用[ ]中括号来进行条件判断,then,表示条件成立需要执行,fi表示if的结束