1、bash脚本编程格式:
顶格写#!/bin/bash
接下来给出一些注释信息,以#开头如:
#description
#version
#auhor ceshi <hello@heelp.com>
#date 2017-11-07
然后代码注释
缩进,适度添加空白行
2、变量介绍:
局部变量
本地变量
环境变量
位置参数变量
特殊变量
3、数据类型:
字符型
数值型
4、bash算数运算:
方法①:let var=$num1 op $num2
方法②:var=$[ expression ]
方法③:var=$((expression))
方法④:var=$(expr argu1 op argu2 )
需要注意的是:
var=变量值 //这是变量赋值
var=$(命令) //这是命令结果引用
有些时候,乘法符号(*)需要转义实现;
5、增强型赋值:在shell脚本中要用let描述
变量做某种算数运算后回存至此变量中:
let i=$i+# //#是数字
let i+=#
此类操作符有:+=、-+、*=、/=,%=
自增:
let var+=1
let var++ //如果每次加“1”,可以写成此种方式
自减:
let var-=1
let var-- //如果每次减“1”,可以写成此种方式
6、练习题:
计算/etc/passwd文件中的第10个用户和第20个用户的uid之和
id1=$(head -10 /etc/passwd | tail -1 | cut -d: -f3)
id2=$(head -20 /etc/passwd | tail -1 | cut -d: -f3)
idsum=$[ $id1 + $id2]
7、shell脚本编程之条件测试(测试表达式)
判断某需求是否满足;需要由测试机制来实现。
如何编写测试表达式以实现所需要的测试:
如#grep "^$" /etc/rc.d/init.d/functions &> /dev/null
#echo $?
①、有专门命令实现测试表达式,使用执行命令,并利用命令状态返回值来判断:
0:成功
1-255:失败
如:查看centos用户是否登陆系统:
#w | grep "^centos\>"
#echo $?
②、没有专门命令实现,这类需要用到测试表达式(如:大小、长短等)
方法一:test expression
方法二:[ expression ] //注意:expression两端必须有空白字符,否则为语法错误
方法三:[[ expression ]]//注意:expression两端必须有空白字符,否则为语法错误
8、bash的测试表达式类型:
数值测试
字符串测试
文件测试
8.1、数值测试:用于实现数值大小比较:
-eq :是否等于;如[ $num1 -eq $num2 ]
-ne :是否不等于
-gt :是否大于
-ge :是否大于等于
-lt :是否小于
-le :是否小于等于
8.2、字符串测试:字符比较;比较时,变量要加引号
== :是否等于 如:[ "tom" =="tmo" ]
> :是否大于
< :是否小于
!= :是否不等于
=~:左侧字符串是否能够被右侧的PATTERN所匹配;可以匹配左侧字符串的部分内容。
-z "string":判断指定的字串“string”是否为空,空则为真,不空为假
-n "string":判断指定的字串"string" 是否为不空,不空为真,空则为假。
注意1:做字符串测试时,要在[[ expression ]]两个中括号中做比较,一个中括号有时是不生效的。
如:#[[ a>b ]]
#echo $?
注意2:字符串要加引号,表示引用,做变量引用时不能用单引号。
8.3、文件测试:
存在性测试:文件的存在性测试,存在为真,不存在为假
-a FILE
-e FILE
文件存在性及类型测试:
-b FILE :是否存在并且为块设备文件
-c FILE :是否存在并且为字符设备文件
-d FILE :是否存在并且为目录文件
-f FILE :是否存在并且为普通文件
-p FILE :是否存在并且为命名管道文件
文件存在性及权限测试:
-r FILE :是否存在并且对当前用户可读
-w FILE :是否存在并且对当前用户可写
-x FILE :是否存在并且对当前用户可执行。
文件存在性及特殊权限测试:
-g FILE :是否存在并且拥有sgid权限
-u FILE :是否存在并且拥有suid权限
-k FILE :是否存在并且拥有sticky权限
-s FILE :是否存在并且有内容,有为真没有为假;小写“s”
文件存在性及时间戳测试:
文件存在性及从属关系测试
双目测试:
FILE1 -eq FILE2 :FILE1与FILE2是否为指向同一文件系统的相同inode的硬链接
FILE1 -N FILE2 :FILE1是否新于FILE2
8.4、组合测试条件:
逻辑运算:
方法一:
command1 && command2
command1 || command2
! command2
方法二:
test EXPRESSION1 -a|-o|!EXPRESSION2
方法三:[EXPRESSION1 -a|-o|!EXPRESSION2 ]
方法四:[[EXPRESSION1 -a|-o|!EXPRESSION2 ]]
如:
[ -o FILE -a -x FILE ] //表示测试用户是否属于当前用户并有执行权限。
9、脚本的状态返回值:
默认是脚本中执行的最后一条命令的状态返回值,可以自定义状态退出状态码,如下:
exit [n] :n为自己指定的状态码;若不指定n,默认0为真,其他为假,
注意:shell进程遇到exit时,即会终止,因此整个脚本执行即为结束。
如:id user3 &> /dev/null && exit 0 || useradd user3
练习1:将当前主机名称保存至hostname变量中;主机名如果为空,或者为localhost.localdomain,则将其设置为www.magedu.com
[root@localhost ~]# hostname=$(hostname)
[root@localhost ~]# [ -z "$hostname" -o "$hostname" == "localhost.localdomain" ] && hostnamewww.magedu.com
10、位置参数变量:向脚本传递参数
位置参数变量格式:
MYSCRIPT ARGU1 ARGU2 //脚本 参数1 参数2
位置参数变量应用方式:$1,$2,.....${10},${...},
如:
有一个脚本如下:
#!/bin/bash
echo "put two arg"
let sum=$1+$2
echo $sum
运行:
[root@localhost ~]# bash ./script 2 3 //其中2 3 为位置参数表示脚本中的$1,$2
put two arg
5
[root@localhost ~]#
位置参数轮替:
格式:shift [n] //一次将n个参数踢出,可以不加n,表示默认一个
如:
#!/bin/bash
echo " firsh pos argus :$1,$3"
shift 2
echo "second pos argus :$1"
运行:
~]# bash ./shift.sh 1 2 3 //一次踢出两个参数,那个再一次给$1赋值 即是第三个数
firsh pos argus :1,3
second pos argus :3
[root@localhost ~]#
练习:
写一个脚本,通过命令传递两个文本文件路径给脚本,计算空白行数之和
1 #!/bin/bash
2 lin1=$(grep "^$" "$1"| wc -l)
3 lin2=$(grep "^$" "$2"| wc -l)
4 echo $[$lin1+$lin2]
运行:
[root@localhost ~]# bash ./line0.sh /etc/fstab /etc/issue
2
[root@localhost ~]#
11、特殊变量
$0:脚本文件路径本身
$#:脚本参数的个数
$*:所有参数,把所有参数当作一个个单独的字符串
$@:所有参数,把所有参数当作一个个字符串来看待
引用9:
脚本的状态返回值:
默认是脚本中执行的最后一条命令的状态返回值,可以自定义状态退出状态码,如下:
exit [n] :n为自己指定的状态码,0为真,其他为假
注意:shell进程遇到exit时,即会终止,因此整个脚本执行即为结束。
如:id user3 &> /dev/null && exit 0 || useradd user3
如下脚本:
1 #!/bin/bash
2 [ $# -lt 2 ] && echo "input two argu" && exit 10
3
4 lin1=$(grep "^$" "$1"| wc -l)
5 lin2=$(grep "^$" "$2"| wc -l)
6 echo $[$lin1+$lin2]
运行:
[root@localhost ~]# bash ./line0.sh /etc/fstab
input two argu
[root@localhost ~]# echo $? //查看执行状态,由于有exit命令,因此不会执行到最后一条语句
10
[root@localhost ~]#
12、过程式编程语言的代码执行顺序: 顺序执行:逐条运行 选择执行:代码有一个或多个 代码有一个分支:条件满足时才会运行 代码有两个或以上分支:只会执行其中一个满足条件的分支 循环执行: 代码片段(即循环体)要执行0次,1次,或多次的循环。 |
|
12.1、选择执行--单分支的if语句 格式一: if 测试条件 then 代码分支 fi 格式二: if 测试条件;then 代码分支 fi |
12.2、选择执行--双分支的if语句 格式: if 测试条件;then 条件为真时执行的分支 else 条件为假时执行的分支 fi |
选择执行示例一: 通过参数传递一个用户名给脚本,此用户不存在时,则添加此用户: 脚本如下: #!/bin/bash if ! grep "^$1\> " /etc/passwd &> /dev/null ;then useradd "$1" echo $1 | passwd --stdin $1 &> /dev/null fi 运行脚本如下: [root@localhost ~]# grep "^zhang\>" /etc/passwd [root@localhost ~]# bash ./user.sh zhang [root@localhost ~]# grep "^zhang\>" /etc/passwd zhang:x:2013:2013::/home/zhang:/bin/bash [root@localhost ~]# |
|
选择执行示例二: 通过参数传递一个用户名给脚本,此用户不存在时,则添加此用户: 脚本如下: #!/bin/bash if [ $# -lt 1 ];then echo "input username" exit 22 fi if grep "^$1\> " /etc/passwd &> /dev/null ;then echo "$1 is exists" fi if ! grep "^$1\> " /etc/passwd &> /dev/null ;then useradd "$1" echo $1 | passwd --stdin $1 &> /dev/null fi exit 222 注意:此shell脚本中有两处exit命令,去掉exit 22,会执行exit 222,用echo $?可以验证,如果在之间有exit 22,则以后的语句就不会再执行了。 |
|
选择执行示例三: #!/bin/bash if [ "$1" -gt "$2" ] then echo " the max is $1" else echo "the max is $2" fi 运行如下: [root@localhost ~]# bash ./max.sh 3 20 the max is 20 [root@localhost ~]# |
示例四, 求两数较大值。 1 #!/bin/bash 2 max=$2 3 if [ "$1" -gt "$2" ] 4 then 5 max=$1 6 else 7 max=$2 8 fi 9 echo "max is $max" 注意:此处事先申明的max=$2有没有都可以, |
选择执行示例四: #!/bin/bash if [ $# -lt 1 ] ;then echo " input at least one argu:" exit 10 fi if grep "^$1\>" /etc/passwd &>/dev/null;then echo "the user:$1 is cunzai" else echo "the user:$1 is not cunzai" exit 100 fi id=$(grep "^$1\>" /etc/passwd | cut -d: -f3 ) echo $id if [ $[$id%2] -eq 0 ];then//判断取余运算 echo $1 is ou shu else echo $1 is ji shu fi 运行如下: [root@localhost ~]# bash ./jIoU.sh lucy the user:lucy is cunzai 2008 lucy is ou shu [root@localhost ~]# bash ./jIoU.sh lily the user:lily is cunzai 2009 lily is ji shu [root@localhost ~]# |
|
选择执行示例五: 通过命令行参数给定两个文件名,如果某文件不存在,则结束脚本执行;如果都存在,则返回每个文件的行数,并说明其中行数较多的文件。 #!/bin/bash echo "input two filename:$1,$2" if [ $# -lt 2 ] ;then echo "the filename_num need two" fi if [ -e "$1" -a -e "$2" ];then echo $(wc -l "$1") echo $(wc -l "$2") else echo at least one is not exists exit 20 fi line1=$(wc -l "$1" | cut -d ' ' -f1) line2=$(wc -l "$2" | cut -d ' ' -f1) if [ "$line1" -gt "$line2" ]; then echo "the filename is $1" else echo "the filename is $2" fi 运行如下: [root@localhost ~]# bash hangshu /etc/fstab /etc/issue input two filename:/etc/fstab,/etc/issue 12 /etc/fstab 3 /etc/issue the filename is /etc/fstab |
注意:有时候脚本在编写的时候会有错误,可以用bash -x来执行检查
"-x"选项可用来跟踪脚本的执行,是调试shell脚本的强有力工具。“-x”选项使shell在执行脚本的过程中把它实际执行的每一个命令行显示出来,并且在行首显示一个"+"号。 "+"号后面显示的是经过了变量替换之后的命令行的内容,有助于分析实际执行的是什么命令。 “-x”选项使用起来简单方便,可以轻松对付大多数的shell调试任务,应把其当作首选的调试手段。