shell编程

12.1 shell简介

在计算机科学中,Shell俗称壳,是操作系统最外面的一层,用来区别操作系统内核,是指“提供给使用者使用界面”的软件。shell管理你与操作系统之间的交互:等待你输入,向操作系统解释你的输入,并且处理各种各样的操作系统的输出结果。同时在Unix类系统中它又是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

 作为用户程序,shell分两大类:

  一:图形界面shell(Graphical User Interface shell 即 GUI shell)

例如:应用最为广泛的 Windows系统的Explorer.exe,Linux系统的GNOME、KDE。

  二:命令行式shell(Command Line Interface shell ,即CLI shell)

例如:MS-DOS系统的COMMAND.COM,Windows系统的cmd.exe;Linux系统的bash、tcsh、csh等。传统意义上的shell指的是命令行式的shell,以后如果不特别注明,shell是指命令行式的shell。

作为命令语言解释器,Shell对命令的解释有两种方式:交互式和非交互式。

  交互式模式就是shell等待你的输入,并且执行你提交的命令。这种模式被称作交互式是因为shell与用户进行交互。这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退。当你签退后,shell也终止了。

shell也可以运行在另外一种模式:非交互式模式。在这种模式下,shell不与你进行交互,而是读取存放在文件中的命令,并且执行它们。当它读到文件的结尾,shell也就终止了。

在Linux系统中查看有哪些shell的方式如图12-1所示。

图 12-1  查看系统shell

在UNIX/LINUX系统中主要有两大类shell:Bourne shell (包括 sh and bash)和C shell (包括 csh and tcsh),其中

Bourne Shell(sh)

首个重要的标准Unix Shell是1970年底在V7 Unix(AT&T第7版)中引入的,并且以它的创始科技部基础条件平台“国家气象网络计算应用节点建设”(2004DKA50730)资助者 Stephen Bourne的名字命名。Bourne shell 是一个交换式的命令解释器和命令编程语言。Bourne shell 可以运行为login shell或者login shell的子shell(subshell)。只有login命令可以调用Bourne shell作为一个login shell。此时,shell先读取系统环境文件/etc/profile,接着读取用户环境文件$HOME/.profile。/etc/profile文件为所有的用户定制环境,$HOME/.profile文件为本用户定制环境。最后,shell会等待读取你的输入。

Bourne Again Shell (bash)

bash是GNU计划的一部分,用来替代Bourne shell。它用于基于GNU的系统如Linux。大多数的Linux(Red Hat, Slackware, Caldera)都以bash作为缺省的shell,并且运行sh时,其实调用的是bash。 bash的环境文件有.bash_profile、.bashrc、.bash_logout、.bash_history,其中.bash_profile是用户登录时第一个执行的环境文件,.bashrc在.bash_profile之后执行,通常用来设置别名,.bash_logout脚本在用户退出时执行,.bash_history则包含用户使用过的命令。缺省shell及bash环境文件如图12-2所示。

图 12-2  Linux系统缺省shell及环境文件

C Shell(csh)

Bill Joy于20世纪80年代早期,在Berkeley的加利福尼亚大学开发了C shell。它主要是为了让用户更容易的使用交互式功能,并把ALGOL风格的语法结构变成了C语言风格。它新增了命令历史、别名、文件名替换、作业控制等功能。

 

Korn Shell(ksh)

  有很长一段时间,只有两类shell供人们选择,Bourne shell用来编程,C shell用来交互。为了改变这种状况,AT&T的bell实验室David Korn开发了Korn shell。ksh结合了所有的C shell的交互式特性,并融入了Bourne shell的语法。因此,Korn shell广受用户的欢迎。它还新增了数学计算,进程协作(coprocess)、行内编辑(inline editing)等功能。Korn Shell 是一个交互式的命令解释器和命令编程语言.它符合POSIX——一个操作系统的国际标准.POSIX不是一个操作系统,而是一个目标在于应用程序的移植性的标准——在源程序一级跨越多种平台。  

 

各主要操作系统下缺省的shell:

AIX 下是Korn Shell。

Solaris缺省的是Bourne shell。

FreeBSD缺省的是C shell。

HP-UX缺省的是POSIX shell。

Linux是Bourne Again shell。

相关命令

#usermod    修改缺省shell,例如管理员用户运行#usermod –s  /bin/tcsh   test命令则将用户test的缺省shell修改为/bin/tcsh。 

$chsh        普通用户可以使用chsh程序来改变自己所使用的shell,例如 $chsh –s  /bin/csh。

12.2 shell编程

为什么要进行shell编程?

在Linux 系统中,虽然有各种各样的图形化接口工具,但是shell仍然是一个非常灵活的工具。Shell不仅仅是命令的收集,而且是一门非常棒的编程语言。您可以通过使用shell使大量的任务自动化,shell特别擅长系统管理任务,尤其适合那些易用性、可维护性和便携性比效率更重要的任务。

12.2.1 常用符号 

1. 注释、通配符、管道

 

#! 符号 指定脚本解释程序名称。

Linux 中有好多中不同的shell,但是通常我们使用bash (bourne again shell) 进行

shell编程,如同其他语言一样,我们可以使用任意一种文字编辑器,比如nedit、kedit、emacs、vi等来编写我们的shell程序。程序必须以下面的行开始:“#!/bin/sh”,其中符号【#!】用来告诉系统它后面的参数是用来执行该文件的程序,即使用/bin/sh来执行脚本程序。

# 符号 程序注释符号,被注释的程序不执行。 “#!”和“#”示例如图12-3所示。

图 12-3  apache启动脚本头部内容

 

?符号 匹配一个字符。 

*符号  匹配0到多个字符,但要注意,不能匹配文件名称前面的圆点和路径名称中的斜线。例如“*file”不能匹配文件“.profile”,只有“.*file”才可以匹配文件“.profile” 。

|符号  管道,将标准输出转到下一个命令的标准输入。

>符号  >file   写入文件file并覆盖旧文件

>>符号 >>fiile  加到文件file的尾部,保留旧文件内容,append。

 

2. 参数符号

 

$符号  shell变量操作符号,如$HOME。

$-符号 使用set及执行时传递给shell的标志位 。

$!符号 最后一个子进程的进程号。 

$#符号 传递给shell script的参数个数。 

$*符号 传递给shell script的参数。 

$@符号 所有参数,个别的用双引号括起来。 

$?符号 上一个命令的返回代码,0代表成功,非0失败。 

$0符号 当前shell的名字。 

$n符号 (n:1-) 位置参数。 

$$符号 进程标识号(Process Identified Number, PID)。

&符号 在后台执行一个进程。 

部分符号使用见图12-4所示。

图 12-4  符号使用示例

图解说明:

#echo $$  显示当前进程的PID是2768也就是bash的进程号。

#echo $0  显示当前shell的名字,这里“-bash”表示用的shell是bash。

#echo $? 上个命令返回代码,0代表成功,非0失败。

#ping 127.0.0.1 >a.log &  将ping的回显写到文件“a.log“中,并且让ping进程在后台运行。如果要回到前台输入命令#fg。

 

3. 反斜杠、引号

\ 符号 反斜杠 backslash-escaped( \ )反斜杠一般用作转义字符,或称逃脱字符,linux如果echo要让转义字符发生作用,就要使用-e选项,且转义字符要使用双引号echo -e "\n";反斜杠的另一种作用,就是当反斜杠用于一行的最后一个字符时,shell把行尾的反斜杠作为续行,这种结构在分几行输入长命令时经常使用。echo命令常用转义含义符号如图12-5所示,和C语言的转义符号有很多类似。

例如运行[root@mail root]# echo -e "\101\ts\ts"将显示如下结果

A       s       s,其中“\101”代表八进制101,转化成字符就是“A”,“\t”代表制表符号,“s”作为正常字符显示。

图 12-5  echo命令中常用转义符号

 

 “”符号  由双引号括起来的字符,除$、倒引号`(Esc键下面的那个键)和反斜线(\)仍保留其特殊功能外,其余字符均作为普通字符对待。 “$"表示变量替换,即用其后指定的变量的值来代替$和变量;倒引号表示命令替换;仅当 “\"后面字符是"$" 、 "`"、" " "、" \ "时, “\"才是转义字符。如果是图12-4中的转义字符(除" \ "外)则用“echo”命令显示时要加参数“-e”来解释否则作为普通字符。转义符告诉Shell不要对其后面的那个字符进行特殊处理,只是当作普通字符。双引号使用如图12-6所示。

图 12-6  双引号使用

图解说明:

# echo  "$HOME\n`hostname`\"\`\$\\"   “$HOME”代表root用户的主目录,由于没有参数“-e”,“\n”作为普通字符显示,“`hostname`”将hostname作为命令执行,显示本机名称,“\"\`\$\\”中的" " "、"`"、"$"、"\"被转义之后作为普通字符显示。

# echo  -e "$HOME\n`hostname`\"\`\$\\"   加了参数“-e”后字符“\n”被解释为转义换行的含义,其它不变。

 

‘'符号 由单引号括起来的字符都作为普通字符出现,除了echo命令带参数“-e”显示echo支持的转义符号。单引号使用如图12-7所示。

图 12-7  单引号使用

图解说明:

# echo   '$HOME\n`hostname`\"\`\$\\'   都作为普通字符显示。

# echo -e  '$HOME\n`hostname`\"\`\$\\'  带参数“-e”后只有“\n”和“\\”作为转义字符处理,分别表示换行和输出“\”反斜线。

 

``符号 倒引号括起来的字符被shell解释为命令行,在执行时,Shell会先执行该命令行,并以它的标准输出结果取代整个倒引号部分。倒引号使用如图12-8所示,其中“STR=`date`”这行就是将倒引号`date`中date命令的执行结果赋值给变量STR。

图 12-8  倒引号使用1

倒引号中可以是单个命令也可以多个命令的组合,如用管道符号;另外倒引号还可以嵌套使用,但要注意嵌套时要用反斜线将其转义,如图12-9所示。

图 12-9 倒引号使用2

 

4. 运算符号

 

 符号  顺序符号,按顺序执行相关命令。

&& 符号 逻辑与操作符可以把两个命令联系起来,其形式为“命令1&&命令2”,先执行命令1,如果命令1执行成功,则执行命令2,如果命令1执行不成功,则不执行命令2,这和C、JAVA语言是一样的。

|| 符号  逻辑或操作符可以把两个命令联系起来,其形式为“命令1||命令2”,先执行命令1,如果执行不成功,则执行命令2,若命令1执行成功,则不执行命令2。

{}符号  复合运算符,即由多个命令组合在一起,在逻辑上算一条命令,类似于C语言的复合语句。使用花括号时在格式上要注意:左括号后面要有一个空格,右括号前面要有个分号,如图12-10所

图 12-10 花括号使用

图解说明:

#{pwd;hostname}    左括号后面没有空格,显示语法错误。

#{pwd;hostname;}   左括号后面没有空格,右括号前面虽然加了分号,还是显示语法错误。

# { pwd;hostname;}  左括号后面有空格,右括号前面有分号,正常运行。

12.2.2 变量及表达式 

1 变量

在shell程序内你可以使用系统定义的环境变量(参见6.2.2节),还可以自己定义变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:

变量名=  要取出变量值可以加一个美元符号($)在变量前面。在编写shell程序时,为了使变量名和命令名相区别,建议所有的变量名都用大写字母来表示。另外在给变量赋值时,等号两边一定不能留空格,若变量中本身就包含了空格,则整个字符串都要用双引号括起来。

图 12-11  变量使用

在您的编辑器中输入以上内容,然后将其保存为一个文件e.sh。之后执行#chmod +x e.sh

使其可执行,最后输入#./e.sh执行该脚本。脚本及执行结果见图12-11所示。

有时我们想要在说明一个变量并对它设定为一个特定值后就不在改变它的值,类似于编程语言的常量,这可以用下面的命令来保证一个变量的只读性:

readonly  变量名

  在任何时候,建立的变量都只是当前shell的局部变量,所以不能被shell运行的其他命令或shell程序所利用,export命令可以将一局部变量提供给shell执行的其他命令使用,其格式为:

export 变量名,也可以在给变量赋值的同时使用export命令:

export 变量名=变量值,使用export说明的变量,在shell以后运行的所有命令或程序中都可以访问到。

 

2 表达式

条件表达式 在shell中条件表达式通常有三个类型表达式:数值表达式、字符串表达式和文件表达式。

(1)数值表达式

arg1 –eq  arg2:arg1等于arg2则为真。

arg1 -ne  arg2:arg1不等于arg2则为真。

arg1 -gt  arg2:arg1大于arg2则为真。

arg1 -ge  arg2:arg1大于等于arg2则为真。

arg1 -lt  arg2:arg1小于arg2则为真。

arg1 -le  arg2:arg1小于等于arg2则为真。

(2)字符串表达式

-z string1:字符串string1长度为0则为真。

-n string1:字符串string1长度不为0则为真。

string1 =string2 :string1 等于string2则为真。

string1 != string2:string1 不等于string2则为真

string1 <string2 :string1 小于string2则为真。

string1 > string2:string1 大于string2则为真。

 

(3)文件表达式

-e file:如果文件file存在则为真。

-r file:如果文件file存在且可读则为真。

-w file:如果文件file存在且可写则为真。

-x file:如果文件file存在且可执行则为真。

-s file:如果文件file存在且至少有一个字符则为真。

-d file:如果文件file存在且为目录则为真。

-f file:如果文件file存在且为普通文件则为真。

-c file:如果文件file存在且为字符型特殊文件则为真。

-b file:如果文件file存在且为块特殊文件则为真。

 

运算表达式 在shell中也能完成简单的算术运算,格式如下:

$[expression]或 `expr  expression`,使用方法如图12-12所示,需要注意的是当用`expr  expression`这种格式时运算符号两边要有空格。

图 12-12  简单运算使用

12.2.3 控制结构 

shell脚本还提供了高级语言才有的循环和条件结构。

(1) if条件语句  if格式如图12-13所示。

图 12-13  if使用格式

需要注意的是在[  条件表达式 ]中左方括号“[”后要有空格,右方括号“]”前要有空格。

 

(2) case条件语句  if条件语句用于在两个选项中选定一项,而case条件选择为用户提供了根据字符串或变量的值从多个选项中选择一项的方法,其格式如图12-14所示。

图 12-14  case使用格式

 

shell通过计算表达式的值,将其结果依次和表达式value1、value2等进行比较,直到找到一个匹配的表达式为止,如果找到了匹配项则执行它下面的命令直到遇到一对分号(;;)为止。在case表达式中也可以使用shell的通配符(“*”、“?”、“[ ]”)。通常用“*”作为case命令的最后表达式以便使在前面找不到任何相应的匹配项时执行“其他命令行”的命令。下面通过一个例子在进一步理解case的用法。

file命令可以辨别出一个给定文件的文件类型,如图12-15所示

图 12-15  压缩文件类型

我们利用这一点写了一个叫做myzip的脚本,该脚本可以自动解压zip,gzip 和bzip2类型的压缩文件,脚本内容如图12-16所示。

图 12-16  解压脚本

在上图脚本中我们使用了一个位置参数$1。该参数包含了传递给该程序的第一个参数值。也就是说,当我们运行命令:#myzip  test.zip时$1就代表字符串“test.zip”。

 

 (3) for循环  格式如图12-17所示。

图 12-17  for使用格式

  变量名可以是用户选择的任何字符串,如果变量名是VAR,则在in之后给出的数值将顺序替换循环命令列表中的$VAR。如果省略了in,则变量VAR的取值将是位置参数。对变量的每一个可能的赋值都将执行do和done之间的命令列表。

 

(4) while和until循环  While循环的格式如图12-18所示。

 

until循环和while循环的区别在于:while循环在条件为真时继续执行循环,而until则是在条件为假时继续执行循环,为真时退出循环,unitl循环示例如图12-20所示。

图 12-20  until使用示例

上图中的“read”用于接收用户的输入,并赋值给变量“IN”。

 

(5)无条件控制语句break和continue

break用于立即终止当前循环的执行,而contiune用于不执行循环中后面的语句而立即开始下一个循环的执行。这两个语句只有放在do和done之间才有效。

12.2.4 shell使用

1 shell运行调试

运行shell的方式:#sh  文件、#./ 文件、#.   文件、#source   文件。如果运行过程出现错误怎么办?这时就需要对程序进行调试,有的时候,调试程序比编写程序花费的时间还要多,shell程序同样如此。调试shell程序的主要方法是利用shell命令解释程序的“-v”或“-x”选项来跟踪程序的执行。“-v”选择项使shell在执行程序的过程中,把它读入的每一个命令行都显示出来。以图12-19所示脚本为例,“-v”选项执行过程如图12-21所示。

图 12-21  shell调试选项“-v”

而“-x”选择项使shell在执行程序的过程中把它执行的每一个命令在行首用一个“+”加上命令名显示出来。并把每一个变量和该变量所取的值也显示出来,因此“-x”选项是最适合调试的选项,“-x”选项执行过程如图12-22所示。

图 12-22  shell调试选项“-x”

 

2 shell脚本参数传递。下面例子演示了shell脚本如何接收传递的参数,如图12-23所示。其中参数$#表示传递给shell脚本的参数个数,参数$*表示传递给shell 脚本的参数内容,参数$1表示传递给shell脚本的第一个参数,也就是“a.txt”,以此类推$2代表第二个参数“b.txt”……。 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值