linux shell脚本编程基本语法
Shell script是利用shell的功能所写的一个“程序”,这个程序是使用纯文本文件,将一些Linux Shell的语法与命令(含外部命令)写在里面,搭配正则表达式、管道命令与数据流重定向等功能,以达到我们所想要的处理目的。Shell script提供数组、循环、条件与逻辑判断等重要功能,让用户也可以直接以shell来编写程序,而不必使用类似C程序来完成相关功能。Shell Script就像是早期DOS年代的批处理文件(.bat)。
编程格式
在写C程序的时候,代码的开头我们通常会给版本信息。shell脚本也不例外。
一般声明如下。
#!/bin/sh
# Program:
# This program shows "Hello World" in your srceen
# History:
# 2017-6-5 liwanneng V1.0.0
echo -e "Hello world"
- 第一行 #!/bin/sh 声明该shell script使用的shell名称,linux默认使用的是bash shell
- 第二行Program后面是程序内容的说明,这个shellscript中,除了第一行外,其他#符号表示注释
- 第四行History后面是时间,作者以及版本信息
- 从echo开始,后面表示程序正文
shell script中常见语法
从屏幕中获取输入
在shell script中,使用read -p 来获取标准输入
例如
#!/bin/sh
# Program:
# This program User input his first name and last name, Program shows his full name
# History:
# 2017-6-5 liwanneng V1.0.0
read -p "Please input your first name:" firstname #提示用户输入,末尾的first为变量名
read -p "Please input your last name:" lastname
echo -e "/nYour full name is :$firstname $lastname" #结果由屏幕输出
其输出结果如图
数值运算,简单的加减乘除
在shell script脚本中,可以使用$( (计算式) )来进行整数数值运算
#!/bin/sh
# Program:
# This program
# History:
# 2017-6-5 liwanneng V1.0.0
echo -e "Please Input TWO numbers\n"
read -p "the first number is:" num1#提示用户输入,末尾的num1为变量名
read -p "the second number is:" num2
product=$(($num1*$num2))
sum=$(($num1+$num2))
red=$(($num1-$num2))
div=$(($num1/$num2))
echo -e "$num1 x $num2 = $product"
echo -e "$num1 + $num2 = $sum"
echo -e "$num1 - $num2 = $red"
echo -e "$num1 ÷ $num2 = $div"
结果:
shell script中的默认变量($0, $1…)
在bashshell中,$0表示脚本程序本身,$1表示脚本程序后面跟的第一个参数,以此类推,$2表示脚本程序后面跟的第二个参数。除了这些数字变量之外,还有一些较为特殊的变量可以在script中使用来调用这些参数。
* $#:表示脚本程序后面跟的参数个数
* \$@:表示 “\$1”, “\$2”, “\$3”之意,每个变量是独立的。
* \$*:表示”\$1c\$2c\$3”,其中c为分隔字符,默认为空格键。
来看个例子
#!/bin/sh
# Program
# Program shows script name, paramters...
# History
# 2017-6-4
echo -e "The script name is $0"
echo -e "Total parameter numher is $#"
[ "$#" -lt 2 ] && echo -e "The number of paramter is less than 2. Stop here. " && exit 0
echo -e "Your whole paramter is $@"
echo -e "Your first paramter is $1"
echo -e "Your second paramter is $2"
执行结果
shell script中的判断
test命令的测试
在linux中,可以使用test命令来测试系统上面某些文件的相关属性。例如,我要检查sh01.sh是否存在使用:test -e ./sh01.sh
单独执行该命令不会显示任何结果,我们可以在后面加上&&以及||来显示结果,如图:
其中 test命令后面跟的 -e表示:判断文件是否存在。除了-e外,test还可以跟其他许多的参数来获取文件或变量的相关属性如
- 关于某个文件名的文件类型判断,如 test -e filename
-e:该文件名是否存在
-f:该文件名是否存在且为文件
-d:该文件名是否存在且为目录
-b:该文件名是否存在且为块设备文件
-c:该文件名是否存在且为字符设备文件
-S:该文件名是否存在且为socket文件(大写S)
-p:该文件名是否存在且为FIFO文件
-L:该文件名是否存在且为链接文件 - 关于文件的权限检测,如test -r filename
-r:该文件名是否存在且具有“可读”权限
-w:该文件名是否存在且具有“可写”权限
-x:该文件名是否存在且具有“可执行”权限
-u:该文件名是否存在且具有“SUID”属性
-g:该文件名是否存在且具有“SGID”属性
-k:该文件名是否存在且具有“sticky bit”属性
-s:该文件名是否存在且为“非空白文件”(小写s) - 两个文件之间的比较,如:test file1 -nt file2
-nt:newer than,判断file1是否比file2新
-ot:older than,判断file1是否比file2旧
-ef:判断file1与file2是否为同一文件,可用在判断hard link的判定上。主要意义在于判定两个文件是否指向统一个inode - 关于两个整数之间的判定,如test num1 eq num2
-eq:equal,num1等于num2
-ne:not equal,num1不等于num2
-gt:greater than,num1大于num2
-lt:less than,num1小于num2
-ge:great equal,num1大于等于num2
-le:less equal,num1小于等于num2 - 判定字符串的数据
test -z string:判定字符串是否为0,若string为空字符串,则为true
test -n string:判定字符串是否为非零,若string为空字符串,则为false - 多重条件判定,例如:test -r filename -a -x filename
-a:两个条件同时成立!例如 test -r file -a -xfile,则file同时具有 r 与 x 权限时,才回传true
-o:任何一个条件成立!例如 test -r file -o -x file,则file具有 r 或者 x 权限时,才回传true
!:反向状态!如test !-x file,当file不具有x时,回传true。
利用判断符号[]
除了利用test命令判断外,我们可以利用判断符号“[]”(英文输入状态下的中括号)来进行数据的判断。这个符号在shell script中经常与if条件判断搭配使用。
在bash的语法中使用“[]”做判断必须要注意的几点
1. 中括号两端需要空格符来分隔
2. 在中括号[]内每个组件都需要有空格来分隔
3. 中括号内的变量和常量最好都用双引号括起来
假如我空格号使用“口”符号来表示,那么在这些地方需要有空格。
口[口"$HOME"口==口"$MAIL"口]口
上面这句话的意思是变量HOME与变量MAIL是否相同的意思,相当于test$HOME=$MAIL
条件判断式
if… then是shell script中常用到的条件判断式。简单来说就是当符合某项条件的时候,就进行某项工作。其格式一般为
if [ 条件1 ] ; then
程序段
#在shell script中用elif,功能类似于C语言中的else if语句
elif [ 条件2 ]; then
程序段
else
程序段
fi #fi表示if的结束
下面来看一个例子
#!/bin/sh
# Program
# This program shows user's choice
# History
# 2017-6-4 liwanneng V1.0.0
read -p "Please input Y/N:" yn
if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
echo "Clever boy! You will Continue"
exit 0
elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
echo "You will interrupt the program!!!"
exit 0
else
echo "Please input Y/y or N/n!"
exit 0
fi
运行结果如下:
利用case…esac判断
在shell script中除了用if…then语句来判断,我们还可以使用case…esac来表示多重条件判断,类似于C语言中的Case语句。其格式为:
case $变量名称 in #关键字为case,还有$符号
"第一个变量内容") #每个变量内容用括号括起来,关键字则为小括号
程序段
;; #每个类型的结尾使用英文输入法状态下的两个分号来表示
"第二个变量内容")
程序段
;;
*) #最后一个变量使用*来表示其他值
exit 1
;;
easc #由esac来表示case语句的最终结尾
来看一个例子
#!/bin/sh
# Program
# Program show "hello" from $1...by using case ...esac
# History
# 2017-6-4 10:32:33
case $1 in
"hello")
echo "Hello,how are you!"
;;
"bye")
echo "bye-bye!"
;;
"") #如果没有输入
echo "You must input parameter, ex> {$0 someword}"
;;
*)
echo "use $0 {hello or bye}"
;;
esac
来看程序执行的结果
whlie do done,until do done 不定循环
在C语言中,经常用到whle循环和for循环来表示程序的反复执行。在shell script中同样有while循环和for循环,只是shell script 中的while和for 的用法与C语言中稍有不同。
while do done不定循环
在shell script中while…done不定循环的常见格式如下
while [ condition ] #中括号内的状态就是判断式
do #do是循环的开始
done #done是循环的结束
while的在英语中的意思是“当…时”,所以while…done这种循环表示当condition条件成立时就进行循环,直到condition条件不成立时才停止循环。
来看一个例子
#!/bin/sh
# Program
# Repet quesstion until input correct answer.
# History
# 2017-6-6 liwanneng V1.0.0
while [ "$yn" != "yes" -a "$yn" != "YES" ]
do
read -p "Please input yes/YES to stop this program:" yn
done
echo -e "OK,you input the correct answer."
上面这个程序为:当满足条件 “$yn” != “yes” -a “$yn” != “YES” 即输入不为yes/YES时,程序一直循环,调用read语句一直等待用户输入。当不满足条件 “$yn” != “yes” -a “$yn” != “YES” 即输入为yes/YES时,程序退出循环,调用echo语句。程序执行结果如图。
until do done不定循环
在shell script中还有一种不定循环 until do done循环,这种循环恰恰与while相反,它是当条件成立时才进行循环,条件不成立时,程序退出循环。其一般格式如下
ubtil [ condition ]
do
程序段
done
同样来看一个例子
#!/bin/sh
# Program
# Repeat question ubtil user input correct answer
# History
# 2017-6-6 liwanneng V1.0.0
until [ "$yn" == "yes" -o "$yn" == "YES" ]
do
read -p "Please input yes/YES to stop the program:" yn
done
echo -e "Ok,you input correct answer."
程序执行结果和上面有while循环的程序执行结果一样。但是程序逻辑却有所区别。当不满足条件”$yn” == “yes” -o “$yn” == “YES” 即输入不为yes或YES的时候,程序一直循环,调用read语句等待用户输入。直到满足条件 “$yn” == “yes” -o “$yn” == “YES” 即输入为yes 或 YES的时候,程序退出循环,执行echo语句。
for … do … done固定循环以及数值处理
相对于while,until的循环方式是必须要“符合某个条件”,for循环则是“已经知道要循环几次”的状态。它的语法是
for var in con1 con2 con3 #var为变量,con1,con2,con3分别为条件1,条件2,条件3
do
程序段
done
上面这段例子的意思是,当变量
var在循环工作时:1.第一次循环时,
var的内容为con1
2. 第二次循环时,
var的内容为con23.第三次循环时,
var的内容为con3
来看一个具体的例子,加入有三种动物分别是cat,dog,bird,每一行都输出一种动物,程序可以写为:
#!/bin/sh
# Program
# Using for ...loop to print 3 animal
# History
# 2017-6-6 liwanneng V1.0.0
for animal in dog cat bird
do
echo "There is ${animal}..."
done
程序执行结果如下
for… do… done的数值处理
除了上面的方法外,for循环还有另外一种写法,也就是C语言中for循环的用法,语句如下:
for ( ( 初始值;限定值;执行步长) )
do
程序段
dne
for后面三串内容的意义:
1. 初始值:某个变量在循环中的初始值,比如常见的 i=1;
2. 限定值:当变量在限定值范围之内,程序一直循环直到超出限定值,如 i<=100;
3. 执行步长:没做一次循环的变化量,如i = i+1;
来看一个具体的例子,输入一个数字num,程序做1+2+3…+num运算
#!/bin/sh
# Program
# Caculate 1+2+3+...$(input)
# HIstory
# 2017-6-6 liwanneng V1.0.0
read -p "Please input a num:" num
for(( i=1; i<$num; i=i+1 ))
do
sum=$(($sum+$i))
done
echo "The result of 1+2+3+...$num is:$sum"
来看程序执行结果
function函数功能
在C语言中我们经常自己封装函数来表示执行同样功能的一段代码,在shell script中同样有function功能。其一般格式为
function fname(){
程序段
}
fname为封装函数的名字,需要注意的是在shell script中不能像C语言一样现在调用函数之前声明,然后可在调用函数之后实现其内容,而只能在调用fname之前就要实现其内容。话不多说,来看例子
#!/bin/sh
# Program
# Use function to repeat information
# History
# 2017-6-6 liwanneng V1.0.0
function printit(){
echo -n "Your choice is :" #加上-n可以不断行继续在同一行显示
}
echo "This program will print your selection."
case $1 in
"one")
printit;echo $1 | tr 'a-z' 'A-Z'#将小写转换成大写
;;
"two")
printit;echo $1 | tr 'a-z' 'A-Z'
;;
"three")
printit;echo $1 | tr 'a-z' 'A-Z'
;;
*)
echo "Usage $0 {one|two|three}"
;;
esac
程序执行结果:
shell script的追踪与调试
是程序就一定有bug,如果程序出了错,在C语言中我们又自己的调试方法。在shell script中有没有办法调试程序呢,答案是有的。我们可以直接以bash的相关参数来进行判断。sh -n/v/x script.sh
- -n:不要执行script,仅查询语法是否正确
- -v:执行script之前,先将script的内容输出到屏幕
- -x:将使用到的script内容显示到屏幕上(经常用到)
懂了以上这些shell脚本编程语法,一般的shell脚本程序看懂应该没问题了。但是要想自己会写shell脚本程序,还得多加练习!多加练习!多加练习!