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中,使用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"结果:
在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"执行结果
在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运行结果如下:
在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来看程序执行的结果
在C语言中,经常用到whle循环和for循环来表示程序的反复执行。在shell script中同样有while循环和for循环,只是shell script 中的while和for 的用法与C语言中稍有不同。
在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语句。程序执行结果如图。
在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语句。
相对于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循环还有另外一种写法,也就是C语言中for循环的用法,语句如下:
for ( ( 初始值;限定值;执行步长) ) do 程序段 dnefor后面三串内容的意义: 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"来看程序执行结果
在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程序执行结果:
是程序就一定有bug,如果程序出了错,在C语言中我们又自己的调试方法。在shell script中有没有办法调试程序呢,答案是有的。我们可以直接以bash的相关参数来进行判断。sh -n/v/x script.sh
-n:不要执行script,仅查询语法是否正确-v:执行script之前,先将script的内容输出到屏幕-x:将使用到的script内容显示到屏幕上(经常用到)懂了以上这些shell脚本编程语法,一般的shell脚本程序看懂应该没问题了。但是要想自己会写shell脚本程序,还得多加练习!多加练习!多加练习!