上篇文章# 罚钱的教训-Linux基础学习,系统学习了Linux常用的命令,不算非常基础,比如awk文本格式化处理、sed批量文本处理、grep等命令,需要在特定使用场景中去使用才能记住,作为后端开发,Linux是我们的必备功课,接下来我们继续攻克Linux Shell脚本方向的学习。
前言
Shell脚本,也是由Linux基础命令构成,通过逻辑判断、循环结构等分支语句将多条语句编写在.sh后缀的文件中,给文件添加执行权限之后,在文件所在目录下执行sh test.sh或者./test.sh,Linux的SHELL内核就会"逐行"执行脚本文件,将执行结果打印到控制台。
脚本参数
就像执行jar包可以通过命令行传递参数一样,shell脚本也可以通过命令行传递参数,通过arg1 arg2 arg3这种方式传递多个参数,参数之间用空格隔开,在脚本中通过$1``$2的方式来获取参数。
几个比较特殊的参数符号
$# #参数个数
$*/$@ #所有参数,通过for循环等可以全部获取
$0 #脚本名称
$1...$N #参数1..参数N
shift [N] #从左到右移除N个参数,默认N=1,后面详解
输入输出
输出:echo\管道\输出重定向等方式都可以将内容输出
输入:从命令行动态输入可以使用read命令
常用的read参数如下:
read -p "please enter your name?" username #-p指定提示信息 usrename用来接收用户输入
read -t 3 #-t执行限制输入的时间为3秒,默认时间间隔是3秒
read -s #-s执行输入内容被隐藏,类似密码这类比较敏感的输入就可以通过-s来指定不让用户看见
变量运算
在linux中,我们通过message="hello,shell script!"的方式来执行变量,然后通过$message来获取变量值,shell脚本中所有的变量值都是一个字符串,数值字符串可以进行正常的数学、逻辑等运算,通过特殊的定义可以用来表示一个字符串数组
数学运算
在shell脚本中,直接执行a=b+1最后得到的只是b+1的字符串,并不能进行正常的数学运算,需要在指定语法中才能进行数学运算
expr:使用到变量通过$变量名的方式引用,且表达式必须在反引号中间,各个符号之间必须有空格
item=expr ` $arg + 2 `
let:各个符号之间不能有空格,通过$变量名引用其他变量
let item=$arg+2
$(())或者$[]:可以进行浮点运算,引用变量直接使用,不必加$
$[arg+2]
$((arg+2))
declare:声明变量之后变量可以直接参与运算
declare i=20,j=30
declare res
res=i+j
命令置换
如果我们需要在脚本中执行某个命令并获取到命令执行之后的结果,必须我需要查看当前所在的目录,就可以使用命令置换的两个常用命令
- 反引号:将需要执行的命令放在反引号中,并赋值之后就可以拿到命令执行结果
`pwd` #获取当前所在目录
$(命令):不要与$(())和$[]混淆
$(pwd) #获取当前所在目录
上面两种方式获取命令执行结果在有管道、重定向、带参数等复杂语句中会报错,可以使用eval会对命令二次扫描处理执行
3.eval:用于处理需要需要二次扫描执行的变量
案例:循环获取命令行参数,通过index逐个获取
#!/bin/sh
int=1
while [ $int -le $# ];do
arg=\$$int
#eval arg=\$$int
echo "$arg"
let int=$int+1
done
执行结果:$int的结果是$1,$2,前面多加一个$表示执行$1,$2拿到参数值,但是最后的输出结果如下,并没有执行拿到参数值,如果修改为eval arg=\$$int之后就可以正常输出参数值,这也是eval的一个特殊用法,用于指定下标获取参数值
数组
- 定义数组
#通过指定所有元素定义数组
array=('A1' 'B1' 'C1')
#将所有元素重组为数组,比如我们将脚本所有命令行参数放在一个新的数组里面或者将数组所有元素传递到函数中时
args=($@)
- 获取数组
${array[0]} #获取数组元素
${#array[*]} #获取数组元素个数
${array[$length-1]} #获取数组最后一个元素
#循环获取数组中的每个元素
3.删除数组元素
unset array[0] #删除第一个元素
unset array[*] #删除所有元素
复杂语句结构
脚本文件与普通简单命令不同的地方就在于可以通过逻辑、循环等结构来处理一些复杂的业务逻辑,比如常见的java重启脚本、监听脚本等
if--elif--else--fi
语法结构
if [ 逻辑条件 ];then #可以在与if或者elif的地方;then或者转行then也可以
#then
elif [ 逻辑条件 ];then
...
else
fi #结束
逻辑判断
- 字符串判断
-z #判断字符串是否为空,为空返回true
-n #判断字符串是否为空,不为空返回true
== #两个字符串内容相同返回true
!= #两个字符串内容不相同返回true
- 运算符判断
d1 -eq d2 #d1=d2返回true
d1 -ne d2 #d1!=d2返回true
d1 -le d2 #d1<=d2返回true
d1 -ge d2 #d1>=d2返回true
d1 -lt d2 #d1<d2返回true
d1 -gt d2 #d1>d2返回true
- 文件判断
-e #判断文件是否存在,文件存在返回true
-f #判断是否是普通文件
-d #判断是否是一个目录
-l #判断是否是一个文件链接
-r #判断是否有读权限
-x #判断是否有执行权限
-w #判断是否有写权限
4.多个条件逻辑连接
-a/&& #条件与,两种写法 不一样
-o/|| #条件或
! #条件非
语法规则
if或者elif语句中包含条件判断语句,写法要符合规则,主要的规则总结如下:
- []中括号两边必须有空格
- 数字的大小比较不能直接用>或者<类似的符号比较,要使用指定方式
- 多个条件连接进行逻辑判断时,可以使用下面三种方式,注意写法上的差距
#写法一 if [ $arg -ge 10 ] && [ $arg -le 30 ];then echo ">=10 <=30" else echo "10" fi #写法二 if [ $arg -ge 10 -a $arg -le 30 ];then echo ">=10 <=30" else echo "10" fi #写法三 if [[ $arg -ge 10 && $arg -le 30 ]];then echo ">=10 <=30" else echo "10" fi
循环
语法结构
#while循环
while [ 条件判断 ];do #可以在于while或者for或者until同行的地方;do或者转行直接do
#do
#exit 中途直接退出整个循环,以下类似
#continue 退出本次循环,进入下次循环,以下类似
done
#for循环
for i in array;do
done
#until循环
until [ 条件判断 ];do
done
举例说明
1.输出1-5之间整数相加结果
# while循环
sum=0
i=0
arraynum=(1 2 3 4 5)
while [ $i -lt ${#arraynum[@]} ];do
let sum=$sum+${arraynum[i]}
let i=$i+1
done
echo "1到5总和:$sum"
i=0
until [ $i -ge ${#arraynum[@]} ];do
let sum=$sum+${arraynum[i]}
let i=$i+1
done
echo "1到5总和:$sum"
for i in ${arraynum[@]};do
let sum=$sum+$i
done
echo "1到5总和:$sum"
2.循环获取所有的脚本入参
$(seq 1 $#)#可以获取从1到某个整数的正整数序列
shift N#可以由左向右溢出N个入参,默认N为1
#方式一
for arg in $@;do
echo $arg
done
#方式二
for i in $(seq 1 $#);do
eval res=$$i
echo "第$i个参数是$$i:$res"
done
#方式三
while [ $# -gt 0 ];do
echo "$1"
shift
done
函数
shell脚本中的函数定义与其他常规语言定义不太一样,不需要指定入参,只需要传递就可以,可以传递数组作为入参,在函数中通过与获取脚本参数类似的方式获取,以函数最后一行语句执行结果作为函数出参,一般在函数或者脚本命令执行成功之后,通过访问$?来获取执行结果,正常执行结束后结果都为0,命令行执行多条命令可以通过&&符号连接执行
查看脚本执行结果
./age.sh && echo $?
自定义print函数
#!/bin/bash
print(){
args=($@)
for arg in ${args[*]};do
echo $arg
done
}
print "study" "shell" "script"
写在最后
Linux Shell脚本开发学习之路暂时到这里就结束啦,后面我会继续努力,持续更新所学所想,与大家一起分享。文章如有不足之处,欢迎大家留言、评论指正,点赞、收藏也可以,谢谢哦!