shell脚本编程入门
编程语言介绍
编程语言分为:机械语言、汇编语言和高级语言;
计算机能识别的语言为机械语言,而人类能学习的并且能够方便掌握的为高级语言,所以,我们所编写的程序就要通过编译来转换成为计算机能识别的机械语言来运行,这个过程我们叫做编译。所以,我们能够学习的一般都为高级语言;
高级语言又分为两种:静态语言和动态语言;
静态语言:编译型语言,例如C、C++、JAVA、C#等,这种语言所编写的程序,在程序开始运行前就会将程序所有的代码编译完成,再一起执行;
动态语言:解释型语言,例如python、shell、.net、perl、php等、它运行程序是解释一句运行一句;
静态语言我们也叫做强类型语言,因为,如果你想要使用变量,则这个变量的数据类型必须在调用之前定义好,没有定义数据类型的变量是无法运行的;而动态语言也叫弱类型语言,弱类型语言的变量可以不用定义,语言可以为我们自动识别;
最后,编程语言又分为两种模型:面向对象和面向过程的;
面向对象是把整个项目作为一个一个的对象来实现(分块),所以面向对象的开发语言更加适合于大型项目的开发,例如JAVA、python、perl、c++;
而面向过程的是把编程着眼点主要放在问题本身,例如C语言、shell脚本语言、perl等;
【编程语言没有所谓的好与不好一说,而是只有“最合适”的说法】
变量
变量:就是给计算机内存中的一段空间命令,命令的这个空间就叫做变量,而再给这个空间放入值的过程,我们就叫做给变量赋值;
bash下的变量的内部数据类型:(这是数据在内存中存放的格式,默认情况下,shell程序下一班都不会去申明数据类型,所以,我们的bash程序默认数据为字符类型)
字符型(string)
数值:整型(int)、浮点型
布尔类型:真假
同时,脚本一般在执行的时候都会自动启动一个子shell进程,命令行中的启动的脚本会继承当前shell环境变量(也就是我们自己通过 bash ./xx.sh 命令执行的脚本程序),为了能够让程序运用源shell下的Linux命令,我们就需要运行 #!/bin/bash 来让系统识别这个脚本程序中用到的Linux命令,以及调用相应的环境变量来执行程序;
bash下的支持变量类型:
环境变量
作用域为当前shell进程以及其子进程(脚本会自己再运行一个子进程)
export VARNAME=VALUE #export导出,也就是环境变量的定义方式;
或者先定义变量再导出也可以
VARNAME=VALUE
export VARNAME
我们可以通过命令:printenv、env、export 来查看当前的环境变量,如果想要在启动时候就需要导入环境变量,可以考虑将命令保存在profile或则bashrc文件中去;
本地变量(局部变量)
只对当前的bash程序有效,所以我们再shell脚本程序中定义的变量,基本上都是本地变量;例如:NAME=Jerry #在bash下直接定义一个变量,在这个bash进程下生效;
局部变量则是在这个bash进程下的一段代码中生效;例如:local VARNAME=VALUE #定义局部变量,只对当前的代码(作用域)生效;
位置变量
$1、$2、$3 ... 以此类推
这个变量主要和传参有关,它用来调用外部输入的参数,替换到shell脚本程序中去;
特殊变量
$? 用来判断上一条名的运行结果(0:表示上一条命令运行正确,非0:则表示错误,不同的数值代表不同的错误,其中1、2、127三个值是保留值,其他的错误值都可以自己定义)
【有时候我们并不需要一条命令的输出内容,而是只需要判断命令是否正常运行,这时候我们结合 /dev/null 以及输出重定向和 $? 来做即可;例如:id student &> /dev/null | echo $? #判断是否存在student这个用户】
$# 表示脚本运行输入的传参的个数
$@
$*
变量的赋值:VAR_NAME=VALUE (这里我们需要知道的是变量的命名,必须具有可读性,这里没有硬性要求,完全是编程规范)
变量的调用:我们通过 ${VARNAME} 的方式来调用变量,如果其中VARNAME是一个独立的字符串,则 {} 一般都会被省略掉;但是有时候又不能省略,例如:
ANIMAL=pig
echo "There are some ${ANIMAL}s." #这里的 {} 就不能省略,如果省略了,$ANIMALs 这个变量系统就无法识别了;
撤销变量:所有的变量定义的时候,我们都省略了set命令,现在我们要撤销变量赋值关系,或则删除变量,就需要通过unset来执行;例如:unset VARNAME 即可;
shell脚本中的条件判断
一般来说,在编写程序脚本的时候我们需要有一定的逻辑才能让脚本程序继续运行,而这一切都来自于计算机对于条件语句的判断,而条件语句又分为哪些常见的类型呢?逻辑运算符在条件判断语句中又起什么作用呢?Linux下shell脚本的条件判断语句又如何使用呢(包括if语句)?
1、整数条件判断:数值的比较
整数的比较:-eq(等于)、-nq(不等于)、-gt(大于)、-lt(小于)、-ge(大于等于)、-le(小于等于)
2、字符测试:字符串或者命令行运行的情况
3、文件测试:用户、文件等是否存在
文件是否存在:-e FILE(判断文件是否存在(单目运算符))、-f FILE(判断文件是否为普通文件 -)、-d FILE(指定所判断的文件是否为目录)、-r -w -x FILE(判断当前用户对所要判断的文件或者目录是否具有可读、可写、可执行的权限)
[ -e /etc/inittab ] #测试/etc/inittab文件是否存在
[ -x /etc/rc.d/rc.sysinit ] #判断/etc/rc.d/rc.sysinit文件是否具有执行权限
4、逻辑运算符使用:
逻辑与:一个为假,结果一定为假 &&
逻辑或:一个为真,结果一定为真 ||
id user1 &> /dev/null && echo "Hello,student." #如果user1存在,则命令id user1 &> /dev/null运行正常,为真。那就必须执行后面 echo "Hello,student."的命令;
id user1 &> /dev/null || echo "Hello,student." #如果user1存在,则命令id user1 &> /dev/null运行正常,为真。那么后面的命令就不再执行了;所以,上面我们一般结合起来使用:
id user1 &> /dev/null && echo "Hello,student." || echo "No student." #这条命令也就是说,id user1执行正确,为真,则运行"Hello,student."。否则为假,则运行"No student.";
5、条件测试写法:
[ expression ] 或者 [[ expression ]] 或者 test expression;第一方式使用较多;【记住:判断语句的前后一定要添加一个空格符】
结合1、2、3点,我们来做一下判断:
USERID=`id user1 &> /dev/null | echo $?` #将id user1的执行结果赋值给USERID这个变量
[ $USERID -eq 0 ] #判断USERID是否为0,
6、if语句的条件判断:
除了通过 && || 来做条件判断后执行对应的命令外,我们还可以通过if语句来做条件判断后的行为!这也是我们将来最常用的方式!
单分支if语句
if 判断条件; then
statement1
statement2
...
fi 【shell脚本语句在语句结束的时候都需要有结束符】
双分支if语句
if 条件判断; then
statement1
statement2
...
else
statement3
statement4
...
fi
多分支if语句
if 判断条件1; then
statement1
...
elif 判断条件2; then
statement2
...
elif 判断条件3; then
statement3
...
fi
【在if语句中,对于条件判断只识别真和假,如果判断的是数值,那么0就是真,而其他数据均为假】
shell脚本中的算数运算
在shell脚本下如何实现1+2=3呢?如果我们定义A=1,B=2,C=$A+$B,但是很遗憾,这样C的记过为“1+2”,而并不是我们需要的3,所以在shell脚本下面我们对于算数运算有特定的格式:
1、通过 let 算数运算表达式 来进行算数运算
2、通过 $[算数运算表达式] 来进行运算
3、也可以通过 $((算数运算表达式)) 来进行运算
4、expr 算数运算表达式 的格式也可以进行运算
shell脚本的错误排查
一般情况下,脚本出现错误的话,在运行的时候就会提示;
如果不想在脚本运行的时候才看到错误,那么我们使用 bash -n 的命令可以详细查看脚本错误;而 bash -x 则可以详细的显示脚本每一步运行的过程;