Liunx学习笔记 - 07 - 03 shell script(shell脚本)

Liunx学习笔记 - 07 - 03 shell script(shell脚本)

1 何为shell script

shell script(程序化脚本)是利用shell的功能所写的一个程序,这个程序使用纯文本文件,将一些shell的语法和命令(含外部命令)写在里面,搭配正则表达式、管道命令与数据流重定向等功能,达到我们想要的处理目的。

所有的编程语言都是由Hello World引入的,所以写个Hello World的shell脚本看看。

vim sh01_HelloWorld.sh	# vim新建并编辑sh01_HelloWorld.sh文件

敲入该文件内容如下:

#!/bin/bash
# Program:
#     This program shows "Hello World!" in your screen.
# History:
# 2019/12/30    by Mei Guanhua

echo "Hello World!"
exit 0

说明:

第一行#!/bin/bash说明该script使用的shell类型为bash,这一行必不可少,默认写法;

后面#开头的为注释行;

echo "Hello World!"为主命令,即向屏幕输出Hello World!字符串;

最后一行exit 0的意思是结束程序,并输出个0,这个0给到了环境变量?里,即表明程序正确执行了,当然,也可以用exit 非零数值来定义特定的错误类型。

写好该文件后,wq!保存退出vim编辑器即可。

如何运行该脚本呢?可以:

sh sh01_HelloWorld.sh # sh命令来执行该脚本,执行结果:
Hello World!

chmod 755 sh01_HelloWorld.sh 	# 先把该脚本权限改成能执行x的
./sh01_HelloWorld.sh			# 直接执行就好了,执行结果:
Hello World!

2 简单范例

例1-交互式脚本,键盘读入用户姓名并输出到屏幕

#!/bin/bash
# Program:
#     This program reads users' name from keybord, and then output them.
# History:
# 2019-12-30 Meiguanhua
read -p "Please input your first name: " firstname  # 提醒用户输入名
read -p "Please input your last name: " lastname	# 提醒用户输入姓
echo "\nYour full name is: $firstname $lastname" 	# 屏幕输出用户名和姓
exit 0

例2-简单的数值运算

#!/bin/bash
# Program:
#     This program reads 2 integers and multiply them.
# History:
# 2019/12/30    by Mei Guanhua
echo -e "Please input two integers, I will multiply them."
read -p "first number: " firstNum
read -p "second number: " secondNum
total=$(($firstNum*$secondNum))
echo "$firstNum * $secondNum = " $total
exit 0

实际上,还可以用source XXX.sh来执行脚本,其和sh XXX.sh的区别是,sh的执行方式执行后,脚本中的变量为局部变量,而source执行后,脚本中的变量使全局变量(环境变量),其不会消失。

3 判断式

3.1 test命令的测试功能

test可以检测文件是否存在及其相关属性,比如要检查一个文件存在否,可以:

test -e fileName	# 检测fileName文件存在否

可惜没有任何返回和显示,其实存在?变量里了,可以

test -e fileName && echo "exist" || echo "not exist"
测试标识代表意义
存在及类型 ,例 test -e fileName 表示是否存在
-e该文件名是否存在
-f该文件名是否存在且为文件
-d该文件名是否存在且为目录
-b该文件名是否为一个blcok device设备
-c该文件名是否为一个character device设备
-S该文件名是否为一个Socket文件
-p该文件名是否为一个FIFO(pipe)文件
-L该文件名是否为一个链接文件
权限测试,例 test -r fileName表示是否可读
-r检测该文件名是否存在且具有“可读”的权限
-w检测该文件名是否存在且具有“可写”的权限
-x检测该文件名是否存在且具有“可执行”的权限
-u检测该文件名是否存在且具有“SUID”的权限
-g检测该文件名是否存在且具有“SGID”的权限
-k检测该文件名是否存在且具有“Sticky bit”的权限
-s检测该文件名是否存在且为“非空白文件”
两文件之间的比较,例 test file1 -nt file2
-nt(newer than)判断file1是否比file2新
-ot(older than)判断file1是否比file2旧
-ef判断file1与file2是否为同一文件,可用来判断hard link硬链接,即判断两文件是否为同一inode
两个整数间的判断,例 test n1 -eq n2
-eq两数值相等(equal)
-ne两数值不等(not equal)
-gtn1大于n2(greater than)
-ltn1小于n2(less than)
-gen1大于等于n1(greater than or equal)
-len1小于等于n2(less than or equal)
判定字符串的数据
test -z string判定字符串是否为0,若为空字符串,则为true
test -n string判定字符串视为非0,若为空字符串,则为false,-n可省略
test str1=str2判定str1是否等于str2,相等则为true
test str1!=str2判定str1是否不等于str2,相等则为false
多重条件判断,例:test -r filename -a -x filename
-a两个条件同时成立
-o任何一个条件成立
!反向状态,例test ! -x file,则file不具有x权限为true

例3-判断文件是否存在及其权限:

#!/bin/bash
# Program:
#     Judge a file type.
# History:
# 2019-12-30 Mei Guanhua

echo "Please input a filename, then I will check its type and permissions. \n\n"

# 让用户输入文件名,并且判断该文件名是否为空,若为空,则直接跳出脚本
read -p "Please input a filename: " filename
test -z $filename && echo "You MUST input a filename!!" && exit 1

# 判断文件是否存在,若不存在则显示信息并结束脚本
test ! -e $filename && echo "The filename '$filename' DO NOT exist!!" && exit 2

# 判断文件属性和类型
test -f $filename && filetype="regular file"
test -d $filename && filetype="directory"
test -r $filename && perm="readable"
test -w $filename && perm="$perm writable"
test -x $filename && perm="$perm executable"

# 输出文件信息
echo "The filename: $filename is a $filetype ."
echo "Its permissions are: $perm ."
exit 0

3.2 利用判断符号[]

与test语法相同,还可以用中括号[]来表示数据的判断,例如判断变量myName是否为空,可以:

[ -z "$myName" ]; echo $?

注意,使用中括号时,中括号两端必须要有空格符来分隔,且中括号内的每个部分都要用括号来分隔,括号内的常量最好都用单引号或者双引号包括起来。

例4-根据用户输入的y/Y或n/N来显示yes或no:

#!/bin/bash
# Program
#     This program shows the choice of user.
# History
# 2019-12-30 Mei Guanhua

read -p "Please input (Y/N): " yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue!" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "OK, interrupt!" && exit 0
echo "I don't know what your choice is. " && exit 1

3.3 shell script的默认变量($0、$1)

实际上,脚本执行的时候,可以在后面跟上变量,就跟咱们有时候写程序,函数名后面跟一堆输入参数一样的,那么如何在脚本中来使用这些变量呢?shell对这些变量有默认的名字,即脚本文件名为变量$0,第1个参数为$1,第2个参数为$2,以此类推。

此外,还有几个特殊的变量:

  • $#表示后接参数的个数
  • $@表示"$1" “$2” “$3”,每个变量用双引号括起来
  • $*表示"$1 $2 $3",即用空格间隔开的每个变量
  • $@和$*还是略有区别的,但是一般用$@就好了。

例5-显示shell script的默认变量:

#!/bin/bash
# Program:
#     This program test the script name, parameters...
# History:
# 2019-12-30 Mei Guanhua

echo "The script name is      $0"
echo "Total parameters is     $#"
[ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." \
	&& exit 0
echo "Your whole parameter is '$@'"
echo "The 1st parameter is    $1"
echo "The 2nd parameter is    $2"

测试及结果

./sh07_scriptName.sh var1 var2	# 运行该脚本,后跟俩参数var1和var2,显示如下
The script name is      ./sh07_scriptName.sh
Total parameters is     2
Your whole parameter is 'var1 var2'
The 1st parameter is    var1
The 2nd parameter is    var2

还可以用shift来使变量做偏移操作,其实就是向左卡掉几个变量的意思

例6-偏移变量

#!/bin/bash
# Program:
#     This program test the effect of shit function.
# History:
# 2019-12-30 Mei Guanhua

echo "Total parameter number is $#"
echo "Your whole parameter is   '$@'"

shift
echo "Total parameter number is $#"
echo "Your whole parameter is   '$@'"

shift 3
echo "Total parameter number is $#"
echo "Your whole parameter is   '$@'"

测试及运行结果

./sh08_shiftTest.sh var1 var2 var3 var4 var5 # 测试变量偏移,后跟5个变量,显示如下:
Total parameter number is 5
Your whole parameter is   'var1 var2 var3 var4 var5'
Total parameter number is 4
Your whole parameter is   'var2 var3 var4 var5'
Total parameter number is 1
Your whole parameter is   'var5'

4 条件判断式

跟所有的编程语言一样,也提供了if类型的判断结构和case类型的判断结构。

4.1 利用if…then

单重判断的语法:

if [ 条件判断式 ]; then
    条件判断式成立时,进行的操作;
fi	# 把if反过来写表示if的结束

多重判断的语法:

if [ 条件判断式 ]; then
    条件判断式成立时,进行的操作;
else
    条件判断式不成立时,执行的操作;
fi

更多嵌套分支的语法:

if [ 条件判断式1 ]; then
    条件判断式1成立时,进行的操作;
elif [ 条件判断式2 ]; then
    条件判断式1不成立,且,条件判断式2成立时,执行的操作;
else
    条件判断式1和2都不成立,执行操作;
fi

条件判断式的写法和3.2小节的一样,如果有多个条件的组合,可以把它们放到一个中括号里,用-a、-o连接,或者把每个条件放到一个中括号里,然后用逻辑运算符号将其连接起来,&& 表示与,|| 表示或。

例7-根据用户输入的y/Y或n/N来输出yes或no,用if…then实现:

#!/bin/bash
# Program
#     This program shows the choice of user.
# History
# 2019-12-30 Mei Guanhua

read -p "Please input (Y/N): " yn

if [ "$yn" == "Y" -o "$yn" == "y" ]; then
	echo "OK, continue!"
	exit 0
elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
       	echo "OK, interrupt!"
	exit 0
else
	echo "I don't know what your choice is. "
	exit 0
fi

4.2 利用case…esac

这个类似C++里面的switch,可以多重分支判断,判断变量吻合哪项内容就去做哪部分的操作,如果哪部分都不符合那就执行默认部分的操作,语法:

case $变量名 in
  "第1个变量内容")
    程序段
    ;;
  "第2个变量内容")
    程序段
    ;;
  *)
    exit 1
    ;;
esac

例8-如果用户输入和参数hello,则回复Hello,不然就提示输入字符串:

#!/bin/bash
# Program
#     Check $1 is equal to "hello".
# History
# 2019-12-30 Mei Guanhua

case $1 in
	"hello")
		echo "Hello, how are you?"
		;;
	"")
		echo "You MUST input parameters, ex> {$0 someword}"
		;;
	*)
		echo "ex > {$0 hello}"
		;;
esac

4.3 function功能

子函数也是编程语言所必须的,bash同样提供该功能,语法:

function funName() {
    程序段
}

注意,函数一定要放在调用前面。

例9-让用户选择输入one、two、three:

#!/bin/bash
# Program
#     Use function to repeat information.
# History
# 2019-12-30 Mei Guanhua

function printit() {
    echo "Your choice is $1"	# 注意这里的$1为function执行时的默认第1个变量值,也就是下面的1、2、3
}

echo "This program will print your selection!"
case $1 in	# 注意这里的$1为该脚本调用时输入的第1个变量值,即用户输入第1个参数值
	"one")
		printit 1
		;;
	"two")
		printit 2
		;;
	"three")
		printit 3
		;;
	*)
		echo "Usage $0 {one|two|three}"
		;;
esac

5 循环loop

循环也是必不可少的,同样提供有while和for型循环

5.1 while do done,until do done(不定循环)

语法:

while [ condition ]
do
    程序段;	# 条件满足时执行动作
done
until [ condition ]
do
    程序段;	# 执行该动作直到condition满足时退出循环
done

两个比较类似,以吃饭为例,前者是我饿着呢所以就一直吃,后者是我吃啊吃直到吃饱为止。

例10-用户要是不给我yes/YES我就让他一直输:

#!/bin/bash
# Program
#     Repeat question untile user input correct answer.
# History
# 2019-12-30 Mei Guanhua

while [ "$yn" != "yes" -a "$yn" != "YES" ]
do
	read -p "Please input yes/YES to stop this program: " yn
done

echo "OK! You input the correct answer."

例11-用户不断输入直到输了yes/YES为止:

#!/bin/bash
# Program
#     Repeat question untile user input correct answer.
# History
# 2019-12-30 Mei Guanhua

until [ "$yn" == "yes" -o "$yn" == "YES" ]
do
	read -p "Please input yes/YES to stop this program: " yn
done

echo "OK! You input the correct answer."

例12-从1加到100:

#!/bin/bash
# Program
#	This program add 1 to 100 using while loop
# History
# 2019-12-30 Mei Guanhua

s=0
i=0

while [ "$i" != "100" ]
do
	i=$(($i+1))
	s=$(($s+$i))
done

echo "The result of '1+2+3+...+100' is $s"

5.2 for do done(固定循环)

语法:

for var in con1 con2 con3 ...
do
    程序段;
done

第1次循环式,$var的值为con1;
第2次循环式,$var的值为con2;
第3次循环式,$var的值为con3;
……

例13-输出动物园里已有的动物种类:

#!/bin/bash
# Program
#     Using for loop to print 3 animals
# History
# 2019-12-30 Mei Guanhua

for animal in dog horse elephant
do
	echo "There are ${animal}s..."
done

5.3 for do done的数值处理

语法:

for (( 初始值; 限制值; 终止步长 ))
do
    程序段;
done

例14-从1加到n:

#!/bin/bash
# Program
#	This program add 1 to 100 using for loop
# History
# 2019-12-30 Mei Guanhua

read -p "Please input a number, I will calculate 1+2+3+...+your_input: " nu

s=0
for ((i=1; i<=$nu; i=i+1))
do
	s=$(($s+$i))
done

echo "The result of '1+2+3+...+$nu' is $s"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值