shell基本编程与trap的命令,用户在线例子
先写一个脚本
先写一个Shell脚本文件
1 #!/bin/bash #脚本默认开头
2
3 echo "hello!"
默认没有执行权限x,可通过chmod添加
$ sudo chmod +x T01.sh #添加执行权限
$ bash T01.sh #通过bash执行脚本
$ ./T01.sh #直接执行脚本
一、变量
- 局部变量:仅限于命令行,或Shell脚本文件中。
- 全局变量:Shell进程及其所有子进程
- 可以使用export内置命令将局部变量设置为全局变量 ,用法:export 局部变量名
- 变量三种:普通变量(用户自定义的变量)、系统预定义的环境变量(PATH)和命令行变量(KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲、*)
- 给变量赋值的时候等号两边不能有空格,引用变量需要在前面加$即可。
- 环境变量的设置(每个环境变量都用大写字母表示)
$ myname="hello I am xiaona!" #普通变量赋值
$ echo $myname #引用普通变量
$ env #查看系统环境变量
$ export PATH=dir/ #修改PATH的变量为dir/
$ export PATH=$PATH:dir/ #PATH再增加一个目录(增加新的值需要使用:分隔开,不该便原有的值)
$ source ~/.bashrc #使刚添加的环境变量生效
- 命令行变量
# 命令行变量
$ ./T01.sh abcd 1234 #以这行命令为例子
# $0 保存的当前脚本名字(文件名字)
# $# 代表命令行的参数个数,即2
# $* 代表所有的参数,即abcd、1234
# $@ 代表所有的参数,即abcd、1234
# $n 代表第n个参数,如$1表示abcd,$2表示1234
# 两个特殊变量 $?和$$
# $? 代表最后一个命令的返回值
# $$ 代表当前Shell的进程号PID
# $! 后台运行的最后一个进程的PID号
# $- 使用set及其执行时传递给Shell的标志位
特殊符号引号、竖杠(管道)和重定向
- 引号3种,反引号`` 单引号’’ 双引号””
-
单引号:单引号内不允许任何变量、元字符、通配符、转义符被shell解析,均被原样输出。
-
双引号:保护特殊元字符和通配符不被shell解析,但是允许变量和命令的解析,以及转义符的解析。
-
反引号:反引号的功能是命令替换,在反引号(``) 中的内容通常是命令行,程序会优先执行反引号中 的内容,并使用运行结果替换掉反引号处的内容。
-
- 竖杠(管道):前一个命令的输出都作为下一个命令的输入(依次配合完成)
- 重定向(>、<、>>、<<)
- Linux的三种设备
- 标准输入:stdin, 由0表示,默认接收为键盘的输入
- 标准输出:stdout,由1表示,默认输出为终端窗口
- 标准错误:stderr, 由2表示,默认输出为终端窗口
- Linux的三种设备
$ ls notexist 2> a.txt #(notexist是一个不存在的文件,所以将错误信息重定向到a.txt中)
$ echo 0< a.txt #echo读取a.txt的内容
$ echo "hello world" 1>&2 #重定向到标准错误设备
# 在脚本中,在重定向的右边,标准输入、标准设备文件描述符要写成&0、&1和&2
字符串的处理
$ echo "${#var}" #计算var变量的字符数
$ echo "${var#apple}" #删除var变量的左边字符串apple
$ lev=${var%%[a-zA-Z]*} #删除var变量的右边字符串
# 从右到左 %%贪恋匹配(尽可能多的匹配) %无贪恋原则(尽可能少的匹配)
# 从左到右 ##贪恋匹配 #无贪恋原则
二、测试语句
- test语句和方括号[ ]完全等价
- 参数置换:“参数可以是位置参数,也可以是另一个变量”
语法 | 功能 |
---|---|
变量=${参数:-word} | 如果设置了参数,则用参数的值置换变量的值,否则用word置换 |
变量=${参数:=word} | 如果设置了参数,则用参数的值置换变量的值,否则word赋给参数,然后word替换给变量 |
变量=${参数:?word} | 如果设置了参数,则用参数的值置换变量的值,否则就显示word并Shell退出 |
变量=${参数:+word} | 如果设置了参数,则用参数的值置换变量的值,否则不进行置换 |
- 算术运算 格式: $ [表达式]
- 表达式是整数、变量和运算符组成的有意义的式子。
- bash的三种逻辑运算符 !、&&和||;其优先级为! > && > ||
- bash允许使用圆括号是表达式成为整体,圆括号的优先级最高。
三、语法单元
1、分支控制
- 单分支语句
# 单分支语句
if [ -e file ] && [ -r file ] then #file文件是否存在,是否可读
cat file #查看该文件
fi
- if-else的多分支写法
## if-else的多分支写法
if [ -e file ] && [ -r file ] then #方括号内的左右两边都要空格隔开
cat file
elif [ -e file ] then
chmod u+r file #授予读权限
cat file
else #只有else不需要then,其他的if-else的分支都需要then
touch file
fi
- case分支的写法
## case分支的写法
read VAR #从键盘接收一个用户输入,付给变量VAR
case $VAR in #判断VAR变量的值
1) echo "one";; #若值为1,则输出one
2) echo "two";; #每个分支都必须以双分号作为结束(最后一个分支除外)
*) echo "unknown" #星号*匹配任意字符
esac #必须以esac结尾,1可以是'1'
2、循环控制(三种)
- while的循环
##while的循环
declare -i n=0 #declare -i 表示该变量为数值
while [ $n -le 100 ] #条件n小于等于100循环
do #循环提用do和done包含起来
echo "$n"
n=$n+1 #变量n的自加1
done
- until的循环
##until的循环
declare -i n=0 #declare -i 表示该变量为数值
until [ $n -gt 100 ] #条件n小于等于100循环 until是条件不成立执行循环体
do #循环提用do和done包含起来
echo "$n"
n=$n+1 #变量n的自加1
done
- for的循环
##for的循环
files=`ls` #当前目录下的文件名放在变量files中 每个值以空格分开
for i in $files #遍历files
do
if [ -f $i ] then #若是普通文件
wc -l $i #计算$i 该文件的行数
fi
done
#或者for的另一种写法
##for的循环
for((i=1;i<=10;i++)) #双括号的for循环
do
sum=$(expr $sum + $i) #expr支持算术运算
echo $sum #求和输出sum
done
3、函数(判断用户是否在线)
##定义函数和函数调用
check_user() #定义函数 ()中无空格
{
if [ $1 = "quit" ] then #若位置参数第一个为quit,则立即退出
exit # $0表示文件名,位置参数0,exit表示退出命令
fi
USER=`who | grep $1 | wc -l`
if [ $USER -eq 0 ] then
return 0 #return 该函数结束
else
return 1 #用户在先返回1,不在线返回0
fi
}
while true #死循环
do
echo -n "input a user name:" # echo -n 表示不换行
read USER #接收键盘输入
#上面的的等效写法
# read -p "input a user name:" USER
check_user $USER #函数调用 并传递参数$USER
if [ $? -eq 1 ] then # $?是上一步命令执行的结果接收变量;这里值函数调用后传来的参数值
echo "[$USER] online."
else
echo "[$USER] offline."
fi
done
4、trap的命令
- trap的使用
#### trap的使用
$ trap "" INT #当脚本收到信号SIGINT时,忽略该信号
$ trap do_something INT QUIT HUP #当脚本收到信号INT、QUIT或HUP时执行函数do_something
$ trap on_exit EXIT #当脚本正常退出时,执行on_exit函数
#当脚本正常退出时执行函数on_exit,当脚本文件收到某个信号INT或HUP时执行空指令
#此时冒号代表一个空指令,如果没有冒号,脚本将完全忽略该信号,不做响应,不能立即退出
#执行顺序时由下而上,即先执行冒号空语句,再执行EXIT的执行函数on_exit函数
$ trap on_exit EXIT
$ trap ":" INT HUP
- trap的经典使用
$ trap -l #产看系统默认支持的信号类型前缀SIG可以忽略