Bash Shell 编程.docx
- 文档编号:30037166
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:78
- 大小:783.45KB
Bash Shell 编程.docx
《Bash Shell 编程.docx》由会员分享,可在线阅读,更多相关《Bash Shell 编程.docx(78页珍藏版)》请在冰豆网上搜索。
BashShell编程
第十九章BashShell编程
[课前思考]
1.为什么要使用Shell脚本?
Shell脚本文件的结构如何?
如何使脚本文件运行起来?
2.什么是位置参量?
Linux系统中如何表述?
位置参量与set命令有何关系?
3.如何在脚本中编写条件判断转移语句?
如何编写循环语句?
4.你能对系统中的文件进行检测吗?
能编写一个菜单式的选择脚本吗?
19.1介绍
当命令不是从命令行开始执行而是从一个文件开始,这个文件就叫做Shell脚本,这种模式叫做非交互模式。
当bash开始非交互模式的时候,它就开始寻找环境变量,BASH_ENV(ENV)和启动文件(通常是.bashrc)并给它们赋值。
在读取环境变量文件后,bash开始执行脚本。
19.1.1建立Shell脚本的步骤
Shell脚本通常在编辑器中编写,由命令和注释组成。
注释通常以#开头,用于说明程序将要做什么事情。
1.第一行
在脚本左上角的第一行用来说明程序执行脚本中的哪一行。
这行通常被称为shbang行,写作:
#!
/bin/bash
2.#!
#!
被称为魔术数字(magicnumber),用于供内核确认哪个程序将翻译并执行这个脚本。
该行必须在脚本的第一行。
。
3.注释
注释是以#开头的,可以是单独的一行也可以在脚本命令以后和脚本命令共占一行。
它们用来说明脚本做什么,在没有说明的情况下,脚本有时是很难理解的。
虽然注释很重要,但是在多数情况下它们是无用的。
注释不仅仅是为了给别人看也是为了提醒自己,也许两天后你就无法清楚地记得你现在想做什么了。
4.脚本的组成
bash脚本由Linux命令、bash命令、程序结构和注释组成。
5.使脚本可执行
当你创建一个文件后,它并没有执行的权限。
你需要权限去执行它,通过chmod可以将其权限改变为可执行的。
[实例19.1]通过chmod改变脚本文件myscript的权限,使其变为可执行。
[说明]
1.执行chmod命令前,可见myscript是不可执行的程序。
2.用户、组和其他人都可以用chmod命令改变文件权限。
3.ls命令显示这个文件对于所有的用户都是可以执行的,末尾的星号表示这是个可执行程序。
6.脚本会话
以下例子,用户在编辑器中创建一个文件。
文件保存后,并没有执行权限,使用chmod命令,使其执行权限就被打开,接着执行脚本。
如果程序出现错误,则Shell就会立刻响应。
[实例19.2]对greetings脚本进行修改权限,然后执行此脚本。
[说明]
1.脚本的第一行#!
/bin/bash向kernel确认脚本的翻译执行程序是bash
2.注释不可执行,它们单独占据一行或者追加在命令后面。
3.在变量替换以后,echo命令在屏幕上显示引号内的文字。
4.在命令替换以后,echo命令在屏幕上显示引号内的文字。
5.执行ls命令,注释被Shell忽略。
6.echo命令显示双引号内的字符串。
双引号中的变量和命令被替换,但是在这里引号不是必要的。
19.2读取用户输入
19.2.1变量
在上一章节中我们讨论了变量的声明和复位。
变量可以是本地变量供当前的Shell使用,也可以是环境变量。
除非Shell脚本还需要启动其他脚本,否则变量都用作本地变量在当前的脚本中使用。
要从变量中提取值,就在变量前加美元符号。
可以把变量用双引号引用,美元符号会被Shell解释为变量值提取。
在单引号中,变量值是无法提取的。
[实例19.3]
19.2.2read命令
read命令是用于从终端或者文件中读取输入的内建命令,见表19-1。
read命令读取整行输入,每行末尾的换行符被翻译为null(空字符串)。
如果没有指定名称,读取的行就被赋值给一个特定的变量REPLY。
你也可以使用read命令,使得程序停下来等待用户输入回车。
read命令的-r选项忽略反斜杠——换行符,斜杠作为行的一部分;read命令共有四个选项,-a、-e、-p、以及-r。
表19-1read命令
格式
含义
readanswer
从标准输入读取输入并赋值给变量answer
readfirstlast
从标准输入读取输入到第一个空格或者回车,将输入的第一个单词放入变量first中,并将该行其他的输入放在变量last中
read
从标准输入读取一行赋值给内建变量REPLY
read-aarrayname
把单词清单读入一个叫作arrayname的数组里
read-e
在命令行状态下打开命令行编辑。
如果编辑器是vi,那么在提示符下就可以直接使用vi命令了。
read-pprompt
打印提示,等待输入,并将输入储存在REPLY中
read-rline
允许输入包含反斜杠。
[实例19.4]read命令的应用范例。
[说明]
1.read命令从用户那里得到一行输入,并把它赋值给变量answer。
2.read命令从用户那里得到一行输入,并把第一个单词赋值给变量first,第二个单词赋值给middle,剩余部分赋值给变最last。
3.read命令从标准输入得到一行,并把它赋值给REPLY变量。
4.打印变量REPLY的值。
5.通过-p选项,read命令产生个提示“Enteryourjobtitle:
”,并把输入的行保存在变量REPLY中。
6.显示变量REPLY中所包含的字符串。
7.要求用户输入。
8.通过-a选项,read命令把输入作为一个单词数组。
该数组被称为friends,数组元素读入了Melvin、Tim和Ernesto。
9.打印数组friends的第三个元素,Ernesto,数组下标从0开始。
[实例19.5]read命令的应用范例。
[说明]
1.检查是否是根用户,否则打印错误信息并退出。
2.建立一个“here”文档并在屏幕上打印错误信息。
3.read命令等待用户的输入。
当用户按下回车,变量JUNK接受用户的输入,该变量没有实际用处。
这里read命令用来等待用户关闭打印机,返回并输入回车。
4.lpd停止打印守护程序(daemon)。
5.显示“现在请把打印机打开”。
6.用户被提示在准备好以后按下回车键。
7.不论用户输入什么,只要按下回车,程序就恢复执行。
8.1pd启动打印守护程序。
19.3数学计算
19.3.1整数(declare命令和let命令)
1.declare命令
用declare-i命令可以将变量声明为整数。
如果将字符串赋值给整数变量,bash将把0赋值给该变量。
数学计算可以发生在整数变量之间。
如果你想把一个浮点数赋值给整数变量,bash就报告语法错误。
整数变量可以接受不同进制的数,比如二进制、十进制以及十六进制等等。
[实例19.6]整数赋值与计算范例。
[说明]
1.用declare-i命令创建一个整数变量num。
2.给整数变量num赋值一个字符串hello,导致这个变量的值为0。
3.除非使用let命令,否则空格必须被引用或者删除。
4.删除空格,进行数学计算。
5.进行乘法计算,结果赋值给num。
6.引用空格以便进行乘法。
7.向整数变量赋值一个浮点数,导致出现语法错误。
2.整数变量清单
declare-i命令后面不加任何参数,将显示所有的整数变量和它们的值。
3.表达和使用不同的进制
数字可以表达为二进制数、十进制数和十六进制数等等。
[格式]
variable=base#number-in-that-base
[实例19.7]采用二进制赋值。
n=2#101Baseis2;number101isinbase2
[实例19.8]多种进制的应用。
[说明]
1.declare函数用于给整数变量x赋八进制值017,八进制数必须以O开头。
017的十进制值为15,打印该十进制值。
2.把二进制数101赋值给变量x,二进制数必须以2#开头。
打印二进制数101的十进制数5。
3.把八进制数17赋值给变量x,八进制数必须以8#开头,打印x的十进制数为15。
4.把十六进制数b赋值给变量x,十六进制数必须以16#开头,打印x的十进制数11。
4.let命令
let命令是bash的内建命令,用来做数学计算和数字表示法检测。
要想了解你的bash版本支持哪些let操作,输入命令:
helplet
[实例19.9]let命令使用方式例子。
[说明]
1.将5赋值给变最i。
2.let命令使得变量i增加1。
当进行数学计算时,变最替换不需要$。
3.如果参数包含空格就需要引用。
4.快捷操作符号+=表示把变量值增加1。
5.变量i被赋值为3。
6.双括号用来替代let命令,先给变量i增加4,然后再赋值给变量i。
7.先在i中减少2,然后再赋值给i,也可以写为i-=5。
19.3.2浮点数学计算
bash主要支持整数的数学计算,如果需要进行更加复杂的计算,可采用bc、awk和nawk等实用程序,这个部分本书不进行介绍。
19.4位置参量与命令行参数
19.4.1位置参量
信息可以通过命令行传递给脚本。
在脚本名称后面以空格分隔的单词称为参数。
命令行参数在脚本中可以按照其位置提供参考作用。
例如:
$1表示第一个参数,$2表示第二个参数,依此类推,到$9以后,就用括号把数字括起来防止混淆。
例如第十个参数,就表示为${10}。
变量$#用来判断参数的个数,而$*用来显示所有的参数。
用set可以设置或者重置位置参量。
当使用set命令时,所有位置参量的值都被清空。
位置参量的含义参见表19-2。
表19-2位置参量
位置参量
含义
$0
引用脚本名称
$#
获取位置参量的个数
$*
列位置参量清单
$@
同上
“$*”
扩展为一个参数
“$@”
扩展为彼此分隔的参数
$1…${10}
引用单个位置参量
[实例19.10]位置参量的使用范例。
[说明]
1.在脚本greetings2中,位置参数$0表示脚本名称。
$l表示第一个命令行参数,$2表示第二个命令行参数。
2.脚本greetings2中没有任何参数传递,输出说明脚本的名称叫作greetings2,因为没有参数,所以变最$1和$2为空,什么也不打印。
3.这次。
有一个参数Tommy被传递给脚本,Tommy被赋值给位置参量1。
4.输入两个参数Tommy和Kimberly。
Tommy被赋值给$1,Kimberly被赋值给$2.
19.4.2set命令和位置参量
set命令可以用来重置位置参量。
一旦重置,旧的参考变量清单就丢失了。
恢复位置参量用命令set--,$0永远是脚本名。
[实例19.11]应用set命令来重置位置参量范例。
[说明]
1.脚本名储存在变量$O中。
2.$*表示所有位置参量。
3.$1表示第一个位置参量。
4.$2表示第二个位置参量。
5.$#表示表示位置参量的个数。
6.所有的位置参量都保存在变量oldargs中。
7.set命令允许你重置位置参量,清除旧的参量列表,现在,$1是Jack,$2是Nicky,$3是Scotte。
8.$*表示所有变量,Jack、Nicky和Scotte。
9.$#表示表示位置参量的个数是3。
10.$1是Jack。
11.命令替换以后,位置参量成为date命令的输出。
12.显示新的$2、$3和$6。
13.打印变量oldargs。
14.用set变量从oldargs中建立位置参量。
15.显示前三个位置参量。
[实例19.12]位置参量应用。
[说明]
1.特殊变量编辑符?
检查$1中是否有值,如果没有就退出脚本,打印信息。
2.若不带参数运行,$1将不被赋值,显示错误信息。
3.给程序checker一个命令行参数,Sue,$1被赋值为$1。
继续运行程序。
1.$*与$@的区别
$*与$@的区别只有在用双引号引用时二者才有区别。
双引号中的$*使得变量变为一个字符串;而双引号中的$@,相当于其中的每一个变量都被双引号引用,每一个单词都被看作分开的字符串。
[实例19.13]$*与$@的使用区别范例。
[说明]
1.设置位置参量。
2.当$*展开的时候,applepie两侧的引号被去掉,apple和pie就成为两个单词。
for循环按照顺序把每一个单词赋值给i,并打印i的值。
每一次循环,左边的单词就被替换,且下一个单词就被赋值给变量i。
3.设置位置参量。
4.用双引号引用$*,整个变量变成一个大的字符串。
applepiepearspeach,整个被赋值给变量i,所以循环只有一次。
5.设置位置参量。
6.不用引号,$*和$@的作用是一样的(见第2句解释)。
7.设置位置参量。
8.用双引号引用$@,每一个位置参量作为单独被引用的字符串。
列出applepie、pear和peaches,这是希望得到的结果。
19.5条件结构和流控制
19.5.1退出状态
条件命令允许我们基于是或否,真或假来处理一些任务。
if是最简单的判断形式;if/else允许我们执行两路判断;if/elif/else允许我们执行多路判断。
bash允许两种类型的条件控制:
命令的成功或者失败,表达式的真或者假。
在两种情况下,都需要使用退出状态。
退出状态值为0表示成功或者为真,否则为失败或者为假。
?
状态变量保存了一个与退出状态值相互对应的数值。
让我们通过看下面的实例19.14,回顾一下退出状态值的工作原理。
[实例19.14]观察退出状态值。
[说明]
1.给变量name赋值为字符串cheng3。
2.grep命令在passwd文件中搜索cheng3。
3.?
状态变量包含最后一个命令的退出状态。
在这个例子中是grep的退出状态。
如果找到了cheng3该值就是O,否则就非O。
4.变量name被赋值为字符串Fred。
5.grep命令在passwd文件中搜索Fred,如果无法找到,?
状态变量的值是1,表示搜索失败。
19.5.2内建test命令
通常用内建的test命令给表达式赋值,这个命令也用来连接括号。
可以使用test命令,或用一系列的括号代替test命令。
只有test命令或者使用方括号时,表达式不能赋值。
因为空格在字符串中用来分隔单词,所以包括空格的单词需要使用引号。
在bash2.x版本中,[[]]可以用来给表达式赋值(内建混合的test命令)。
包含空格的字符串在整体使用时必须被引号引用。
在简单test命令中,逻辑符号&&(逻辑和)和||(逻辑或)可以替代-a或者-o选项。
虽然test命令可以给数学表达式赋值,但最好还是用let给数学表达式赋值,因为它有丰富的类C语言的操作符。
let命令可以利用双括号加以简化。
无论使用test命令、混合命令还是let命令,表达式的结果都将检验,退出状态值是O则表示成功,否则表示失败。
下面的例子用来说明如何使用内建命令test判断退出状态值和test命令的其他形式,一组[]、复合命令[[]]、let命令和(())。
[实例19.15]使用内建命令test判断退出状态值和test命令的其他形式范例,一组[]、复合命令[[]]、let命令和(())。
[说明]
1.给变量name赋值为字符串cheng3。
2.test命令用来给字符串、数字表达式赋值,或者判断文件。
像所有命令样返回退出状态值。
如果是0则表达式为真,否则为假。
等号两边必须有空格,这里判断name的值是不是cheng3。
3.判断失败退出状态值为1。
4.括号是test命令的变形。
第一个括号后而必须有空格。
判断表达式看看变量name的值是不是Tom。
在判断字符串的时候bash允许使用一个或者两个等号。
5.退如状态值为O,说明$name等于cheng3。
6.test命令不允许使用通配符。
?
被看作是问号而不是通配符。
判断失败,退出状态值为1,表示第8行出现错误。
7.x和y被预先给定为数字。
8.Test用数字关系运算操作判断表达式,这里判断如果$x大予$y就返回O,表示真,否则返回非O数。
9.判断$x是否小予$y,返到O表示为真,返列1表示为假。
[实例19.16]
[说明]
1.如果使用复合命令test,Shell元字符可以用在字符串判断中。
这个表达式判断中变量name是不是等于Tom、tom或者tommy。
如果表达式是真,退出状态值就是O。
2.逻辑运算符号&&(逻辑和)和||(逻辑或)都可以参与复合判断。
如果使用&&,两个表达式就必须同时为真,如果第一表达式就为假,判断就停止了;使用||时如果有一个表达式为真,整个表达式就为真,因此如果第一个表选式为真,判断就不继续了。
注意,“Jose”是被引用的。
如果不是被引用就测试变量friend是否包含模式Jose。
这个例子因为第二个表达式为假所以为假。
3.内建命令shopt打开了扩展模式匹配。
4.把Tommy赋值给变量。
5.这个判断中要判断表达式与使用新的元字符的是否模式匹配。
这个表达式判断变量name是否匹配以字符t或者T开头,紧跟一个o,一个或者多个m,然后是一个y。
[实例19.17]
[说明]
1.x和y赋值为数字。
2.如果x大于2退出状态值就是0,因为条件为假,所以退出状态值为1。
注意变量赋值的时候,如果使用(()),美元符号就不是必须的。
3.如果x小于2,退出状态值就是0,否则为1。
4.复合表达式赋值。
表达式判断如下:
如果x等于2同时y等于3,退出状态值就为0,否则为1。
5.复合表达式赋值。
表达式判断如下:
如果x大于2或者y小于3,退出状态值就为0,否则为1。
表19-3test命令操作符
判断操作符
判断是否为真
字符串判断
[string1=string2]
string1等于string2
[string1=string2]
string1等于string2
[string1!
=string2]
string1不等于string2
[string]
string不空
[-zstring]
string长度是0
[-nstring]
string长度非0
[-lstring]
string长度
逻辑判断
[string1-astring2]
string1和string2都是真
[string1-ostring2]
string1和string2是真
[!
string1]
string1不匹配
逻辑判断(复合判断)
[[pattern1&&pattern2]]
pattern1和pattern2都是真
[[pattern1||pattern2]]
pattern1或pattern2是真
[[!
pattern]]
pattern不匹配
整数判断
[int1-eqint2]
int1等于int2
[int1-neint2]
int1不等于int2
[int1-gtint2]
int1大于int2
[int1-geint2]
int1大于等于int2
[int1-ltint2]
int1小于int2
[int1-leint2]
int1小于等于int2
文件判断中的二进制操作
[file1-ntfile2]
file1比file2新
[file1-otfile2]
file1比file2旧
[file1-effile2]
file1与file2有相同的设备或者I结点数
注:
逻辑判断中,pattern可以包含元字符;在字符串判断中,pattern2必须包含在引号中。
表19-4let命令操作符
操作符
含义
-+
一元减和加
!
~
逻辑否
*、/、%
乘、除、余数
+-
加、减
<<、>>
位逻辑左移位、右移位
<=>=<>
比较运算符
==、!
=
等、不等
&
位逻辑与
^
位逻辑非
|
位逻辑或
&&
逻辑和
||
逻辑或
=、*=、/-、%=、+=、-=、<<=、>>=、&=、^=、|=
快捷方式
19.5.3if命令
最简单的判断形式就是if。
if结构后面的命令执行并返回退出状态值,退出状态值通常由程序的作者决定。
如果退出状态值是O,命令成功就执行关键字then后面的语句。
在CShell中,if后面的表达式必须跟C语言一样是一个布尔型的表达式。
但是在其他的Shell中,可以是一组命令。
如果命令退出状态值是0就执行关键字then后面的语句块,直到遇到fi。
fi终止if块。
如果退出状态值非0,则意味着出现了错误,关键字then后面的语句被忽略,执行fi后面的语句。
了解被判断命令的退出状态值是十分重要的。
退出状态值是了解grep是否在文件中搜索到模式所必须依赖的方法。
如果grep成功就返回0,否则返回非O。
[格式]
ifcommand
then
command
command
fi
--------------------------------------------------------
(Usingtestfornumbersandstrings--oldformat)
iftestexpression
then
command
fi
or
if[string/numericexpression]then
command
fi
--------------------------------------------------------
(Usingtestforstrings--newformat)
if[[stringexpression]]then
command
fi
--------------------------------------------------------
(Usingletfornumbers--newformat)
if((numericexpression))
--------------------------------------------------------
[实例19.18]if命令使用范例。
[说明]
1.grep在/etc/passwd文件中搜索参数name,将标准输出和标准错误重新定向到/dev/null。
2.如果退出状态值是O,程序就执行then后面的语句直到fi关键字then与fi之间的语句以缩进的格式书写,是为了增强程序的可读性,为调试提供方便。
3.fi终止了then后面的语句块。
1.exit命令和变量?
exit命令用来结束脚本返回命令行。
如果你希望在某种条件下退出脚本,可以使用该命令。
exit命令的参数是一个在0~255之间的数字。
如果参数是0,则表示顺利退出,而非0参数表示出现了一些
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Bash Shell 编程
![提示](https://static.bdocx.com/images/bang_tan.gif)