嵌入式
Linux05
第5章 Linux Shell编程,本章教学目的及要求掌握shell编程的一般方法。了解shell高级编程技术及shell脚本的调试方法。,Shell是什么?,Shell原意为外壳,用来形容物体外部的架构,Linux系统的Shell作为操作系统的外壳,保护其内部的核(Kernel)。,5.1 Shell简介,Shell是什么,具体来讲,Linux系统的Shell作为操作系统的外壳,为用户提供使用操作系统的接口。它是命令语言、命令解释程序及程序设计语言的统称。1.Shell可称为命令解释器:负责用户和操作系统之间的沟通,把用户下达的命令解释给系统去执行,并将系统传回的信息再次解释给用户,所以,它拥有自己内建的Shell命令集,也能被系统中其他应用程序调用。2.Shell还是一种高级程序设计语言:它有变量、关键字,有各种控制语句,如if、case、while、for等语句,有自己的语法结构。利用Shell程序设计语言可以编写出功能强大的代码程序。,Shell解析命令过程,Shell命令的两种形式:在Shell中,有一些命令(比如改变工作目录命令cd)是包含在Shell内部的。还有一些命令(例如拷贝命令cp和移动命令rm)是存在于文件系统中某个目录下的单独的程序,如/bin目录中。对用户而言,不必关心一个命令是建立在Shell内部还是一个单独的程序。内部命令:.、alias、bg、cd、continue、echo、exec、exit、fg、jobs、pwd、set、shift、test、time、umask、unset和wait。外部命令:grep、more、cat、mkidr、rmdir、ls、sort、ftp、telnet、lp和ps,Shell接到用户输入的命令后首先检查命令是否是内部命令,若不是再检查是否是一个应用程序。然后,Shell在搜索路径里寻找这些应用程序(搜索路径就是一个能找到可执行程序的目录列表)。如果键入的命令不是一个内部命令并且在路径里没有找到这个可执行文件,将会显示一条错误信息。如果能够成功找到命令,该内部命令或应用程序将被系统传送给Linux内核。,Shell解析命令过程,常用的Shell,1Shell种类 Linux中的Shell有多种类型,其中最常见的是Bourne Shell(sh)、C Shell(csh)和Korn Shell(ksh)。三种Shell各有优缺点。Bourne Shell是Unix最初始的Shell,并且在每种Unix上都可以使用。Bourne Shell在Shell编程方面相当优秀,但在处理与用户的交互方面做得不如其他几种Shell。,1Shell种类,Linux中的Shell有多种类型,其中最常见的是Bourne Shell(sh)、C Shell(csh)和Korn Shell(ksh)。三种Shell各有优缺点。Bourne ShellC shell是一种比Bourne shell更适于编程的shell,它的语法与C语言很相似。Tcsh是C shell的一个扩展版本。Tcsh包括命令行编辑、可编程单词补全、拼写校正、历史命令替换、作业控制和类似C语言的语法,它不仅和Bash shell是提示符兼容,而且还提供比Bash shell更多的提示符参数。,1Shell种类,Linux中的Shell有多种类型,其中最常见的是Bourne Shell(sh)、C Shell(csh)和Korn Shell(ksh)。三种Shell各有优缺点。Bourne ShellC shellKorn shell集合了C shell和Bourne shell的优点并且和Bourne shell完全兼容。Linux系统提供了pdksh(ksh的扩展),它支持任务控制,可以在命令行上挂起、后台执行、唤醒或终止程序。,1.Shell种类(1)查看目前Shell版本和linux可用版本($SHELL,/etc/shells)。用户默认选择的shell版本可以在/etc/passwd设定。(2)临时改变Shell版本为csh。rootBC:root#csh rootBC:#csh的提示符为“rootBC:#”,退出Shell使用命令exit。,常用的Shell,2BashBash(Bourne Again Shell)是Bourne Shell的扩展,与Bourne Shell完全向下兼容,并且增加了许多特性。它还包含了很多C Shell和Korn Shell中的优点,有灵活和强大的编程接口,同时又有很友好的用户界面。,常用的Shell,Bash是大多数Linux系统的默认Shell。Bash有以下的优点:1)补全命令。在Bash命令提示符下输入命令或程序名时,若没有输全命令或程序名,按“Tab”键,Bash将自动补全命令或程序名。2)通配符。在Bash下可以使用通配符“*”和“?”。“*”可以替代多个字符,而“?”则替代一个字符。3)历史命令。Bash能自动跟踪用户每次输入的命令,并把输入的命令保存在历史列表缓冲区中。,常用的Shell-Bash,4)别名。在Bash下,可用alias和unalias命令给命令或可执行程序起别名和删除别名,这样就可以用自己习惯的方式输入命令。例1:使用lm代替ls l,常用的Shell-Bash,(5)输入/输出重定向。输入重定向用于改变命令的输入,输出重定向用于改变命令的输出.系统默认的输入为键盘、输出为显示器,输入/输出重定向可以改变输入输出。例2:输出重定向,表示追加,常用的Shell-Bash,(5)输入/输出重定向。,例3:输入重定向,通过键盘输入,输入完成后按下CTRL+D,常用的Shell-Bash,6)管道。管道用于将一系列的命令连接起来,也就是把前面命令的输出作为后面命令的输入。管道的命令是“|”。例:cat mydir.out|grep test|wc l 命令演示:lastlast|grep rootlast|grep root|wc-l,常用的Shell-Bash,7)提示符。Bash有两级提示符。第一级提示符就是登录Shell时见到的,默认为“$”。可以通过重新给PS1变量赋值来改变第一级提示符。当Bash需要进一步提示以便补全命令时,它会显示第二级提示符。第二级提示符默认为“”,可以通过重新给PS2变量赋值来改变第二级提示符。一些特殊意义的字符也可以加入提示符赋值中。8)作业控制。作业控制是指在一个作业执行过程中,控制执行的状态。可以挂起一个正在执行的进程,并在以后恢复执行该进程。,常用的Shell-Bash,组合新命令shell脚本提供了文件名扩展字符 通配符的使用直接使用shell的内置命令echo,exit,pwd,kill灵活地使用数据流 重定向,管道等结构化的程序模块流程控制:顺序,分支,循环在后台执行命令&可配置的环境 别名,提示符,环境变量设置等高级的编程语言shell脚本,Shell的特点,利用编辑器编辑脚本,将脚本命名为.sh(非必须)Shell脚本第一行总是以#!/bin/bash 开头,它通知系统以下的Shell程序使用系统上的Bourne Again Shell来解释。第二行注释中写入脚本名,第三行注释开始写入脚本功能习惯。以下行进入脚本正式编写编写完后给脚本添加执行权限:chmod u+x first运行脚本:./first,怎样写Shell?,一个简单的shell 程序$vi first#!/bin/bash#My first shell script#clearecho Hello,everybody!,注意:在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。,5.2.1变量,像高级程序设计语言一样,shell也提供说明和使用变量的功能。shell变量可以保存诸如路径名、文件名或者一个数字。对shell来讲,所有变量的取值都是一个字符串。Shell程序采用$var的形式来引用名为var的变量的值。Shell有以下几种基本类型的变量:用户定义的变量 shell定义的环境变量位置参数 预定义变量参数置换的变量,5.2 Shell编程基础,(1)用户定义的变量,变量名是以字母或下线符打头的字母、数字和下线符序列,并且大小写字母意义不同。定义变量并赋值的一般形式是:变量名=字符串引用变量值:在变量名前加“$”如果在赋给变量的值中要含有空格、制表符或换行符,那么,就应该用双引号把这个字符串括起来。例如:#names=“Zhangsan Lisi Wangwu”说明一个变量为只读:readonly 变量名,显示变量echo 命令:显示单个变量取值,并在变量名前加$,例如:$myvar=how are you$echo$myvar清除变量使用unset命令清除变量。unset varname显示所有本地shell 变量使用set命令显示所有本地定义的shell变量set,(1)用户定义的变量,数学运算-$,数学运算expr#a=3#b=5#expr$a+$b#expr$a-$b#expr$a/$b#expr$a*$b,变量默认都只是当前shell的局部变量,将变量成为公共变量的格式为:export 变量名 也可以在给变量赋值的同时使用export命令:export 变量名=变量值 使用export说明的变量,在shell以后运行的所有命令或程序中都可以访问到,(2)shell定义的环境变量,shell在开始执行时就已经定义了一些和系统的工作环境有关的变量,这些变量用户还可以重新定义。环境变量可以在命令行中设置,但用户注销时这些值将丢失,因此最好在.bash_profile或/etc/profile 文件中设置环境变量。传统上,所有环境变量均为大写。设置环境变量VARNAME=value;export VARNAME显示环境变量使用env 命令可以查看所有的环境变量。清除环境变量使用unset 命令清除环境变量。,(2)shell定义的环境变量,HOME:用于保存注册目录的完全路径名PATH:用于保存用冒号分隔的目录路径名,shell将按PATH变量中给出的顺序搜索这些目录,找到的第一个与命令名称一致的可执行文件将被执行。$PATH=$HOME/bin:.:/bin:/usr/bin;export PATH TERM:终端的类型。UID:当前用户的标识符,取值是由数字构成的字符串。PWD:当前工作目录的绝对路径名,该变量的取值随cd命令的使用而变化。,常用的shell环境变量,PS1:主提示符,在特权用户下,缺省的主提示符是“#”,在普通用户下,缺省的主提示符是“$”。PS2:在shell接收用户输入命令的过程中,如果用户在输入行的末尾输入“”然后回车,或者当用户按回车键时shell判断出用户输入的命令没有结束时,显示这个辅助提示符,提示用户继续输入命令的其余部分,缺省的辅助提示符是“”。IFS:IFS用作shell指定的缺省域分隔符。原理上讲域分隔符可以是任意字符,但缺省通常为空格、tab键。LOGNAME:此变量保存登录名。SHELL:SHELL变量保存缺省shell,通常在/etc/passwd中已设置,常用的shell环境变量,PS1中可用信息$用$作为提示符显示d显示当前日期h显示主机名s显示shell名t显示当前时间(24)T显示当前时间(12)显示当前时间(AM/PM)u显示用户名v显示bash的版本W显示当前工作目录w显示当前工作路径,位置参数是一种在调用shell程序的命令行中按照各自的位置决定的变量,是在程序名之后输入的参数。位置参数之间用空格分隔,shell取第一个位置参数替换程序文件中的$1,第二个替换$2,依次类推。$0是一个特殊的变量,它的内容是当前这个shell程序的文件名,所以,$0不是一个位置参数,在显示当前所有的位置参数时是不包括$0的,(3)位置参数,表示脚本名称,传递个脚本的参数个数,位置参数,所有的参数值,所有的参数值,位置参数及其引用exam1 m1 m2 m3 m4.$0$1$2$3$4$5$6$7$8.$0始终表示命令名或shell脚本名。shift:就把命令行上的实参向左移一位 命令行:ex7 A B CD E.原位置参数:$0$1$2$3$4$5 移位后:$0$1$2$3$4经shift右移位置参数后,$0的值不会发生变化,位置参数,预定义变量和环境变量相类似,也是在shell一开始时就定义了的变量,所不同的是,用户只能根据shell的定义来使用这些变量,而不能重定义所有预定义变量都是由$符和另一个符号组成的,常用的shell预定义变量有:$#:位置参数的数量$*:所有位置参数的内容$?:命令执行后返回的状态$:当前进程的进程号$!:后台运行的最后一个进程号$0:当前执行的进程名 其中,$?用于检查上一个命令执行是否正确(在Linux中,命令退出状态为0表示该命令正确执行,任何非0值表示命令出错)。$变量最常见的用途是用作临时文件的名字以保证临时文件不会重复,(4)预定义变量,shell在遇到未设置的变量时,将其值作为空串处理。而在实际应用中,对未设置的变量,用户可以根据需要采用不同的处理方式,这可通过变量替换来实现。变量替换提供了三种功能:允许替换未设置变量的隐含值;允许对未设置变量赋值;在访问未设置变量时,提示出错信息。,参数置换的变量,参数置换的变量有四种,这些变量通常与某一个位置参数相联系,根据指定的位置参数是否已经设置来决定变量的取值,它们的语法和功能分别如下。a.变量=$参数-word:如果设置了参数,则用参数的值置换变量的值,否则用word置换。b.变量=$参数=word:如果设置了参数,则用参数的值置换变量的值,否则把变量设置成word然后再用word替换参数的值。注意,位置参数不能用于这种方式,因为在shell程序中不能为位置参数赋值。c.变量=$参数?word:如果设置了参数,则用参数的值置换变量的值,否则就显示word并从shell中退出,如果省略了word,则显示标准信息。这种方式常用于出错指示。d.变量=$参数+word:如果设置了参数,则用word置换变量,否则不进行置换。,参数置换的变量 变量=$参数-word,变量=$参数-word:如果设置了参数,则用参数的值置换变量的值,否则用word置换。,参数置换的变量 变量=$参数=word,变量=$参数=word:如果设置了参数,则用参数的值置换变量的值,否则把变量设置成word然后再用word替换参数的值。注意,位置参数不能用于这种方式,因为在shell程序中不能为位置参数赋值。,参数置换的变量 变量=$参数?word,变量=$参数?word:如果设置了参数,则用参数的值置换变量的值,否则就显示word并从shell中退出,如果省略了word,则显示标准信息。这种方式常用于出错指示。,参数置换的变量 变量=$参数+word,变量=$参数+word:如果设置了参数,则用word置换变量,否则不进行置换。,Shell中除使用普通字符外,还使用了一些特殊字符,它们有特定的含义,如通配符“*”和“?”、管道线(|)及单引号、双引号等。,5.2.2 Shell特殊字符,1一般通配符通配符用于模式匹配,如文件名匹配、路径名搜索、字符串查找等。常用的通配符有四种:(1)*匹配任意字符0次或多次出现。例如,f*可以匹配以f 打头的任意字符串。但应注意,文件名前面的圆点(.)和路径名中的斜线(/)必须显式匹配。(2)?匹配任意一个字符,例如,f?匹配f1、fa、fb等,但不能匹配 f、fabc、f12等。(3)其中有一个字符组,它匹配该字符组所限定的任何一个字符。该字符组可以由直接给出的字符组成,也可以由表示限定范围的起始字符、终止字符及中间一个连字符(-)组成。如,fa-d与fabcd作用相同。(4)!表示不在一对方括号中所列出的字符。例如,f!19.c 表示以f打头,后面一个字符不是数字1至9的.c文件名,它匹配fa.c、fb.c、fm.c等。,2模式表达式模式表达式是那些包含一个或多个通配符的字。bash除支持一般通配符外,还提供了特有的扩展模式匹配表达式,如:(1)*(模式表):匹配给定模式表中“模式”的0次或多次出现,各模式之间以“|”分开。例如,file*(.c.o)将匹配文件file、file.c、file.o、file.c.c、file.o.o、file.c.o、file.o.c等,但不匹配file.h或file.s等。(2)+(模式表)匹配给定模式表中“模式”的1次或多次出现,各模式之间以“|”分开。例如,file+(.c|.o)匹配文件file.c、file.o、file.c.o、file.c.c等,但不匹配file。(3)?(模式表):匹配模式表中任何一种“模式”的0次或1次出现,各模式之间以“|”分开。例如,file?(.c.o)只匹配file、file.c和file.o,它不匹配多个模式或模式的重复出现,即不匹配file.c.c、file.c.0等。,2模式表达式(4)(模式表):仅匹配模式表中给定“模式”的一次出现,各模式之间以“|”分开。例如,file(.c.0)匹配file.c和file.o,但不匹配file、file.c.c、file.c.o等。(5)!(模式表):除给定模式表中的一个“模式”之外,它可以匹配其它任何东西。模式表达式的定义是递归的,每个表达式中都可以包含一个或多个模式。例如file*(.cho.sh)是合法的模式表达式。但在使用时应注意,由于带“*”和“+”的表达式可以匹配给定模式的组合,若利用此种表达式去删除文件就存在危险,有可能误将系统配置文件删除。因此,必须小心使用。,3.引用,引用必要性 在shell中所使用的许多特殊符号也可为其他目的所使用,因此当不需要引用这些字符的特殊含义时,就必须引用加以删除。shell 引用类型:双引号 单引号反引号 反斜线,5.2.2 Shell特殊字符,双引号(“”)如果用双引号“”将值括起来,则括起来的字符串允许出现空格、制表符和换行符等特殊字符,而且允许有变量替换。例1:#MAIL=/var/mail/fk#var=MAIL is path of mailbox#echo var/var/mail/fk is path of mailbox例2:#str=This is n a book#echo strThis isa book,使用双引号能消除被括在双引号中的大部分特殊字符的含义,不能消除的字符有:、!、。例1:#echo Type a*,please Type a*,please例2:#echo“today is date”,单引号()使用单引号消除被括在单引号中的所有特殊字符的含义,即单引号表示内容照原样不动。例4:#BOOK=English book#MSG=BOOK#echo MSG-echo$MSG#$BOOK$MSG 例5:#msg=Today is date#echo msgToday is date,反撇号()当一个字符串被括在反撇号“”中时,该字符串将作为命令被shell解释执行,即用命令的执行结果替换这个字符串本身。要注意反撇号与单引号的区别。例1:#lm=pwd#echo lm/root,例2:#now=date#echo nowdate#now=date#echo now1998年 10月 28日 星期三 17时 51分 56秒 CST例3:#echo“Hostname:hostname”,$()的功能与一样例1:#now=$(date)#echo$now例2:#echo$(pwd)例3:#echo“Hostname:$(hostname)”,转义符()使用转义符消除单个字符的特殊含义,即将紧跟在转义符后面的单个字符按字符本身的实际含义解释。例1:#echo your cost is$5.00#echo“your cost is$5.00”#echo your cost is$5.00例2:转义符具有续行功能#ls-l#ls-l,大括号引用变量的值时,可以用花括号将变量名称括起来,使变量名称与它的后续字符分隔开,如果紧跟在变量名称后面的字符是字母、数字或下划线时,必须要使用花括号。例1:,例2:,1.测试命令,在bash中,命令test用于计算一个条件表达式的值,它们经常在条件语句和循环语句中被用来判断某些条件是否满足。test命令的语法格式:test expression或者 expression例1:测试字符串。/测试字符串8是否等于9/$?表示上一条命令执行后的返回值/其值为假,返回1例2:测试字符串。/省略“test”,改用中括号形式,注意中括号中的空格,