Linux脚本可以被认为是按一定的语法规则将一系列指令组织起来的指令集合。它能实现的功能比简单的命令行要丰富很多,因为脚本可以实现函数,循环,条件跳转等功能
1. linux脚本开头
一般是#!/bin/bash,#!这里指出脚本的解释器。
2. 脚本名通常以.sh作扩展名
需要增加执行权限chmod a+x [script名.sh] 后,才能执行脚本。
3. 变量
变量定义:DIR="$(dirname "$(realpath "$0")")"
变量名引用:echo dir is $DIR #引用时直接在变量名前加$
特殊的变量:
$0表示执行脚本命令行参数第0个(脚本名本身)参数
$1表示第一个参数......
$#表示参数个数
bbb=${@:-$aaa} 当参数不为空时bbb就是参数,否则bbb的值就是变量aaa的值
命令执行的结果,要保存在变量中,需要用反引号引用或者$()引用,如:
files=`ls -a` #注意和files=$(ls -a)等价
4.数组
4.1 定义arr=(hello good morning) #注意,数组定义是用空格分隔各元素,不能用逗号
4.2 引用:echo ${arr[0]} #打印第0个元素
echo ${arr[@]} 或者 ${arr[*]} #打印全部元素
echo ${#arr[@]} #打印数组长度
echo ${arr[@]:1:2} #打印数组第1到2个元素
4.3 数组元素删除 unset arr[1]
4.4 增加元素到结尾 arr+=(soda mum)
4.5 取其中一段 tar=(${arr[@]:1:3})
5. 条件语句if
#!/bin/bash
read -p "Please input score:" score
if [ $score -lt 60 ];then
echo poor
elif [ $score -lt 70 ];then
echo average
elif [ $score -lt 80 ]; then
echo good
else
echo excellent
fi
5.1 条件[]两侧都需要空格分开,条件后接;分号
5.2 -eq相等,-gt大于,-lt小于
5.3 结尾必须跟fi
5.4 if中选项含义:
if [ -e $file ]; 如果文件$file存在,则为真if [ -d $dir ]; 如果$dir是目录,则为真
if [ -r $file ]; 如果$file可读,则为真
if [ -w $file ]; 如果$file可写,则为真
if [ -x $file ]; 如果$file可执行,则为真
if [ -s $file ]; 如果$file文件长度不为0,则为真
if [ -f $file ]; 如果$file为常规文件,则为真
if [ -h $file ]; 如果$file为软链接,则为真
if [ -L $file ]; 如果$file为符号链接,则为真
if [ -n $str ]; 如果$str字符串非空,则为真
if [ -z $str ]; 如果$str字符串为空,则为真
6. 分支语句case
#!/bin/bash
read -p "Please input your score(1~4):" score
case $score in
1)echo poor;;
2)echo average;;
3)echo good;;
4)echo excellent;;
*)echo input error!
esac
语法是:case 变量引用 in 值1)语句1;;值2)语句2..
后面跟每一个可能的值,并且加上后括号,执行的语句结尾需要双;号
*)表示其它值,相当于C语中的default
另外case需要esac表示结尾
7.循环语句 for
7.1 语法1:
for 变量 in 集合
do
执行语句
done
#!/bin/bash
for v in {1..10};do
echo $v
done
集合有很多种形式,可以是:
枚举式的集合: for v in 1 2 3 4 5 6 7 8 9;do
范围式: for v in {3..9};do #默认步长1 for v in {1..9..2};do #指定步长为2
数组: array=(good hello student);for v in ${array[@]};do
命令的结果: for v in $(cat test.txt);do
通配符产生的集合: for v in *.txt;do
7.2 语法2:
C语言风格的for
for (( i = 0; i < 100; i++))
do
执行语句
done
8. 循环语句while
语法
while 退出条件
do
执行语句
done
例1 条件一直是真的循环:
#!/bin/bash
while true
do
echo hello world
sleep 1
done
例2 变量超过条件才能结束的循环:
#!/bin/bash
i=0
while [ $i -lt 10 ];do
echo now i=$i
let "i = i + 2"
done
9.退出循环
9.1 continue用于暂时中止后面的语句,但是循环继续
#!/bin/bash
for i in {1..10};do
if (( $i % 2 ));then
continue
fi
echo $i
done
示例表示当i的值是奇数时,continue了,不执行下面的echo
9.2 break用于直接退出当前循环
#!/bin/bash
i=0
while [ $i -lt 10 ];do
let i++
echo $i
if [ $i -gt 6 ];then
break
fi
done
10. 函数
定义:函数名() {
函数体语句
}
函数参数传递:$1表示第一个参数,$2表示第二个参数...函数返回值,调用函数后,$?就是函数返回值,它是最后一条语句的值,而且是一个小于256的非负整数值,如果需要纯值返回,可以return
#!/bin/bash
cmp(){
if [ $1 -gt $2 ];then
echo $1 is greater than $2
return 1
elif [ $1 -lt $2 ];then
echo $1 is lower than $2
return 2
else
echo $1 is equal to $2
fi
return 0
}
cmp 3 5
echo result is $?
11.关联数组
11.1 即键-值对数组
定义:
declare -A students
students=([Yangyong]=64 [ZhangFeng]=76 [LiQiang]=68)
11.2 对它的操作也可以类似数组那样
echo ${students[Yangyong]} #可以看到,就类似将键替换数组的下标
echo ${students[@]} #输出所有的值
echo ${!students[@]} #加了!号后,变成输出所有的键了
for name in ${!students[@]};do
echo $name is ${students[$name]}
done
unset students[ZhangFeng] #删除元素
students+=([GuangDong]=77 [SiChuan]=98) #增加元素
12.字符串
12.1 字符串定义:str="Hello,"
12.2 字符串拼接:str+="world,dummy"
12.3 载取:echo ${str:2:3}
12.4 echo ${str/world/China} # 把world替换为China并输出,输出Hello,China,dummy
12.5 echo ${str//o/O} # 把所有的o替换为O并输出,输出HellO,wOrld,dummy
12.6 echo ${str#*,} # 从左边开始匹配第一个,及其左边的内容,并删除,输出world,dummy
12.7 echo ${str##*.} # 从左边开始匹配最后一个,及其左边的内容,并删除,输出dummy
12.8 echo ${str%.*} # 从右边开始匹配第一个,及其右边的内容,并删除,输出Hello,world
12.9 echo ${str%%.*} # 从右边开始匹配最后一个.及其右边的内容,并删除,输出Hello
13.正则表达式
13.1 使用正则表达式判断是否匹配,如果匹配,则返回0,否则返回1
[[ $str =~ ^This ]] #判断str是否以This开头
[[ $str =~ test$ ]] #判断str是否以This结尾
[[ $str =~ [a-z]+ ]] #判断str是否包含一个或多个小写字母
[[ $str =~ [0-9]+ ]] #判断str是否包含一个或多个数字
[[ $str =~ "is$" ]] #判断str是否以is结尾
[[ $str =~ ([a-z]+)\. ]] #判断str是否包含一个或多个小写字母后跟一个点,并提取小写字母部分
13.2 匹配结果由变量BASH_REMATCH表示,它本身与BASH_REMATCH[0]是一样的,代表整个匹配项;在匹配项中用圆括号分割,每增加一个圆括号,则多一个子项,子项由BASH_REMATCH[1],BASH_REMATCH[2]...表示:
str=isf123abcdrTG056
[[ $str =~ ([0-9]+)abc(dr[A-Z]?) ]]
echo $BASH_REMATCH 或者 echo ${BASH_REMATCH[0]} 输出:123abcdrT
echo ${BASH_REMATCH[1]} 输出:123 第一个子项即第一个圆括号匹配项
echo ${BASH_REMATCH[2]} 输出:drT 第二个子项即第二个圆括号匹配项
更多的见《5-正则表达式》
14.信号
shell会收到进程传来的一些信号,收到这些信号可以进行相关处理:
14.1 SIGINT:中断信号,编号为2
脚本执行过程中按Ctrl+C中断执行,会收到中断信号,收到此信息后,可作相关处理:
myfun() { #定义一个函数,执行打印信息(也可以按需执行其它操作)
echo $1 $2 $3
}
trap 'myfun get INT signal && exit' SIGINT收到SIGINT后,执行打印get INT signal并且退出
14.2 SIGTERM:表示终止信号,编号为15
进程执行过程中,发送kill命令可向进程发送终止信号
trap 'myfun get SIGTERM signal && exit' SIGTERM #收到SIGTERM后,执行打印get SIGTERM signal并且退出
14.3 下面命令可类似上面的操作处理:
SIGKILL:表示强制终止信号,编号为9,可以用kill -9命令来发送
SIGQUIT:表示退出信号,编号为3,可以用Ctrl+\来发送
SIGSTOP:表示停止信号,编号为19,可以用kill -19命令来发送
SIGCONT:表示继续信号,编号为18,可以用kill -18命令来发送
15.其它
set -x 进入调试模式,可以显示每条指令执行情况
set +x 退出调试模式
set -e 遇到错误退出