Shell脚本编程
变量
变量的定义
变量名的命名规则
- 字母、数字、下划线
- 不以数字开头
变量的赋值,不区分类型,等号两侧不允许出现空格
为变量赋值的过程,称为变量替换
变量名=变量值
- a=123
使用let为变量赋值
let a=10+20
使用let可以计算等号右侧的值
将命令赋值给变量
- l=ls
将命令结果赋值给变量,使用$()或者``
letc=$(ls -l /etc)
将命令赋值给变量,通过访问变量去执行命令可以节省系统资源开销
变量值有空格等特殊字符可以包含在””或’’中
变量的引用
- ${变量名}称作对变量的引用
- echo ${变量名}查看变量的值
- ${变量名}在部分情况下可以省略大括号,例如变量名后面没有跟其他字符的时候
变量的作用范围
默认作用范围
- 定义变量的当前shell
变量的导出
export 变量名
可以使变量在其父进程shell和子进程shell都生效
变量的删除
unset 变量名
删除变量
系统环境变量
环境变量配置文件
数组
1 | 定义数组 |
运算符
赋值运算符
- = 赋值运算符,用于算数赋值和字符串赋值
- 使用unset取消为变量的赋值
- = 除了作为赋值运算符还可以作为测试操作符
算数运算符
基本运算符
* + - * / ** %
使用expr进行运算
expr 4 + 5
符号左右要有空格,只支持整数,不支持浮点数
num=`expr 4 + 5`
数字常量
- let “变量名=变量值”
- 变量值使用0开头为八进制
- 变量值使用0x开头为十六进制
双圆括号
- (( a=10 ))
- (( a++ ))
- echo $((10+20))
- (( a=4+5 ))
test比较
退出与退出状态
退出程序命令
- exit
- exit 10 返回10给shell,返回值非0为不正常退出
- $?判断当前shell前一个进程是否正常退出
测试命令test
test命令用于检查文件或者比较值
test可以做以下测试
- 文件测试
- 整数比较测试
- 字符串测试
test测试语句可以简化为[]符号
-z STRING
字符串长度为0
STRING1 = STRING2
字符串相等,区分大小写
STRING1 != STRING2
字符串不相等,区分大小写
INTEGER1 -eq INTEGER2
整数1等于整数2
INTEGER1 -ge INTEGER2
整数1大于等于整数2,如果使用>=,需使用[[]]
INTEGER1 -gt INTEGER2
整数1大于整数2,如果使用>,需使用[[]]
INTEGER1 -le INTEGER2
整数1小于等于整数2,如果使用<=,需使用[[]]
INTEGER1 -lt INTEGER2
整数1小于整数2,如果使用<,需使用[[]]
INTEGER1 -ne INTEGER2
整数1不等于整数2
-e FILE
文件存在,不区分文件和目录
-d FILE
文件存在并且是一个目录
-f FILE
文件存在并且是一个普通文件
[]符号还有扩展写法[[]]支持&&、||、<、>
使用if-then语句
if [ 测试条件成立 ] 或 命令返回值是否为0
then 执行相应命令
fi 结束
代码示例:
- 输出root
1
2
3
4
5[root@localhost ~]# if [ $UID = 0 ]
> then
> echo root
> fi
root- 什么也没有输出
1
2
3
4
5
6[root@localhost ~]# su - vagrant
Last login: 二 10月 22 02:11:36 UTC 2019 from 10.0.2.2 on pts/0
[vagrant@localhost ~]$ if [ $UID = 0 ]
> then
> echo root
> fi- 执行
1
2
3
4
5
6[vagrant@localhost ~]$ if pwd
> then
> echo success
> fi
/home/vagrant
success- 未执行
1
2
3
4
5[vagrant@localhost ~]$ if pwd1
> then
> echo success
> fi
-bash: pwd1: command not found
使用if-then-else语句
使用if-then-else语句可以在条件不成立时也运行相应的命令
if [ 测试条件成立 ]
then 执行相应命令
else 测试条件不成立,执行相应命令
fi 结束
代码示例:
root用户
1
2
3
4
5
6
7
8
9[root@localhost ~]# if [ $USER = root ] ; then
> echo root user
> echo $UID
> else
> echo other user
> echo $UID
> fi
root user
0普通用户
1
2
3
4
5
6
7
8
9
10
11[root@localhost ~]# su - vagrant
Last login: Wed Oct 23 03:59:20 UTC 2019 on pts/0
[vagrant@localhost ~]$ if [ $USER = root ] ; then
> echo root user
> echo $UID
> else
> echo other user
> echo $UID
> fi
other user
1000
使用if-then-elif-then-else语句可以在条件不成立时也运行相应的命令
if [ 测试条件成立 ]
then 执行相应命令
elif [ 测试条件成立 ]
then 执行相应命令
else 测试条件不成立,执行相应命令
fi 结束
1
2
3
4
5
6
7
8
9
10
11
12[vagrant@localhost ~]$ if [ $USER = root ] ; then
> echo root user
> echo $UID
> elif [ $USER = vagrant ] ; then
> echo vagrant user
> echo $UID
> else
> echo other user
> echo $UID
> fi
vagrant user
1000
嵌套if语句
if条件测试中可以再嵌套if条件测试
if [ 测试条件成立 ]
then 执行相应命令
- if [ 测试条件成立 ]
- then 执行相应命令
- fi
fi 结束
代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13[vagrant@localhost ~]$ if [ $USER = root ] ; then
> echo root user
> echo $UID
> else
> if [ $USER = vagrant ] ; then
> echo vagrant user
> echo $UID
> fi
> echo other user
> fi
vagrant user
1000
other user
分支
case 语句和select 语句可以构成分支
使用 for 循环遍历命令的执行结果
for 循环的语法
- for 参数 in 列表
- do 执行的命令
- done 封闭一个循环
使用反引号或$()方式执行命令,命令的结果当做列表进行处理
使用 for 循环遍历变量和文件的内容
列表中包含多个变量,变量用空格分隔
对文本处理,要使用文本查看命令取出文本内容
- 默认逐行处理,如果文本出现空格会当做多行处理
代码示例:
1
2
3
4
5[root@localhost ~]# touch a.mp3 b.mp3 c.mp3
[root@localhost ~]# for filename in `ls *.mp3`
> do
> mv $filename $(basename $filename .mp3).mp4
> done
C 语言风格的 for 循环
for ((变量初始化;循环判断条件;变量变化))
do
- 循环执行的命令
done
代码示例:
1
2
3
4[root@localhost ~]# for ((i=1;i<=10;i++))
> do
> echo $i
> done
while 循环
while test测试是否成立
do
- 命令
done
代码示例:
1
[root@localhost ~]# while [ a -lt 10 ]
do
(( a++ )) echo $a
done
1
死循环
代码示例:
1
2
3
4[root@localhost ~]# while :
> do
> echo hello
> doneuntil 循环
until 循环与 while 循环相反,循环测试为假时,执行循环,为真时循环停止
代码示例:
1
2
3
4
5
6[root@localhost ~]# a=1
[root@localhost ~]# until [ $a -gt 5 ]
> do
> (( a++ ))
> echo $a
> done
break 和 continue 语句
循环的使用
循环和循环可以嵌套
循环中可以嵌套判断,反过来也可以嵌套
循环可以使用break和continue语句在循环中退出
代码示例:
break
1
2
3
4
5
6[root@localhost ~]# for a in {1..9} ; do
> if [ $a eq 5 ] ; then
> break
> fi
> echo $a
> donecontinue
1
2
3
4
5
6[root@localhost ~]# for a in {1..9} ; do
> if [ $a eq 5 ] ; then
> continue
> fi
> echo $a
> done
使用循环对命令行参数的处理
命令行参数可以使用 $1 $2 … ${10} … $n 进行读取
$0 代表脚本名称
$* 和 $@ 代表所有位置参数
$# 代表位置参数的数量
代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# demo
# for pos in $*
# do
# if [ "$pos" = "hello" ] ; then
# echo $pos $pos
# fi
# done
while [ $# -ge 1 ]
do
if [ "$1" = "hello" ] ; then
echo $1 $1
fi
shift
done
函数
自定义函数
函数用于 ”包含“ 重复使用的命令集合
自定义函数
- function fname(){
- 命令
- }
函数的执行
- fname
函数作用范围的变量
- local 变量名
函数的参考
- $1 $2 $3 … $n
代码示例:
1
2
3
4
5
6
7
8
9
10
11
# demo
checkpid() {
local i
for i in $* ; do
[ -d "/proc/$i" ] && return 0
done
return 1
}