Shell编程基础•在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器)。它类似于DOS下的command.com。它接收用户命令,然后调用相应的应用程序。同时它又是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高阶语言中才具有的控制结构,包括循环和分支。图形界面shell(即GUIshell)•应用最为广泛的WindowsExplorer(微软的windows系列制作系统),还有也包括广为人知的Linuxshell,其中linuxshell包括Xwindowsmanger(BlackBox和FluxBox),以及功能更强大的CDE、GNOME、KD、XFCE。命令行式shell(即CLIshell)•bash/sh/ksh/csh(Unix/linux系统)•COMMAND.COM(MS-DOS系统)•cmd.exe/命令提示字符(WindowsNT系统)•WindowsPowerShell(支援.NETFramework技术的WindowsNT系统)•传统意义上的shell指的是命令行式的shell,以后如果不特别注明,shell是指命令行式的shell。•文字操作系统与外部最主要的接口就叫做shell。shell是操作系统最外面的一层。shell管理你与操作系统之间的交互:等待你输入,向操作系统解释你的输入,并且处理各种各样的操作系统的输出结果。•shell提供了你与操作系统之间通讯的方式。这种通讯可以以交互方式(从键盘输入,并且可以立即得到响应),或者以shellscript(非交互)方式执行。shellscript是放在文件中的一串shell和操作系统命令,它们可以被重复使用。本质上,shellscript是命令行命令简单的组合到一个文件里面。•Shell基本上是一个命令解释器,类似于DOS下的command.com。它接收用户命令(如ls等),然后调用相应的应用程序。较为通用的shell有标准的Bourneshell(sh)和Cshell(csh)。交互式shell和非交互式shell•交互式模式就是shell等待你的输入,并且执行你提交的命令。这种模式被称作交互式是因为shell与用户进行交互。这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退。当你签退后,shell也终止了。•shell也可以运行在另外一种模式:非交互式模式。在这种模式下,shell不与你进行交互,而是读取存放在文件中的命令,并且执行它们。当它读到文件的结尾,shell也就终止了。基本格式•我们可以使用任意一种文字编辑器,比如nedit、kedit、emacs、vi等来编写shell脚本,它必须以如下行开始(必须放在文件的第一行):•#!/bin/sh•...•符号#!用来告诉系统执行该脚本的程序,本例使用/bin/sh。编辑结束并保存后,如果要执行该脚本,必须先使其可执行:•chmod+xfilename•此后在该脚本所在目录下,输入./filename即可执行该脚本。合理使用注释•shell脚本中以#开始的行表示注释,直到该行的结束。我们强烈建议你在脚本中进行适当/合理的注释,这样一来,即便你在相当长时间内没有使用该脚本,也能在短时间内就明白它的作用和工作原理。此外,还有一个很重要的原因是,在注释的帮助下,别人可以快速有效的分享你的脚本,并提出自己的意见和改进。变量赋值和引用•Shell编程中,使用变量无需事先声明,同时变量名的命名须遵循如下规则:•首个字符必须为字母(a-z,A-Z)•中间不能有空格,可以使用下划线(_)•不能使用标点符号•不能使用bash里的关键字(可用help命令查看保留关键字)•需要给变量赋值时,可以这么写:•变量名=值•要取用一个变量的值,只需在变量名前面加一个$:•#!/bin/sh•#对变量赋值:•a=helloworld•#打印变量a的值:•echoAis:$a•挑个自己喜欢的编辑器,输入上述内容,并保存为文件first,然后执行chmod+xfirst使其可执行,最后输入./first执行该脚本。其输出结果如下:•Ais:helloworld•有时候变量名可能会和其它文字混淆,比如:•num=2•echothisisthe$numnd•上述脚本并不会输出thisisthe2nd而是thisisthe;•这是由于shell会去搜索变量numnd的值,而实际上这个变量此时并没有值。这时,我们可以用花括号来告诉shell要打印的是num变量:•num=2•echothisisthe${num}nd•其输出结果为:thisisthe2nd•Shell脚本中有许多变量是系统自动设定的,我们将在用到这些变量时再作说明。除了只在脚本内有效的普通shell变量外,还有环境变量,即那些由export关键字处理过的变量。本文不讨论环境变量,因为它们一般只在登录脚本中用到。Shell里的命令•Unix命令•在shell脚本中可以使用任意unix命令,不过实际上最为常用的一般都是那些文件和文字操作相关的命令。下面介绍一些常用命令的语法和功能:•ls•文件列表•wc–lfile或wc-wfile或wc-cfile•分别计算文件的行数(line)、单词数(word)和字符数(character),file为待计算的文件名•cpsourcefiledestfile•文件拷贝,sourcefile为源文件路径,destfile为目的文件夹路径•mvoldnamenewname•重命名文件或移动文件•rmfile•删除文件•grep'pattern'file•在文件内搜索字符串或和正则表达式匹配的字符串•cut-bcolumnfile•将指定范围内的文件内容输出到标准输出设备(屏幕)上。比如:输出每行第5至9个字符cut-b5-9file.txt,注意不要和cat命令混淆,这是两个完全不同的命令•catfile.txt•输出文件内容到标准输出设备(屏幕)上•filesomefile•取得文件somefile的文件类型•readvar•提示用户输入,并将输入内容赋值给变量var•sortfile.txt•对file.txt文件所有行进行排序•uniq•只输出文件中内容不一致的行,如:sortfile.txt|uniq•expr•进行数学运算,如要进行2+3的运算,命令为:expr2+3•find•搜索文件,如根据文件名搜索:find.-namefilename-print•tee•将数据输出到标准输出设备(屏幕)和文件,比如:somecommand|teeoutfile•basenamefile•返回不包含路径的文件名,如:basename/bin/tux会返回tux•dirnamefile•返回文件所在路径,如:dirname/bin/tux会返回/bin•headfile•打印文本文件开头几行•tailfile•打印文本文件末尾几行•sed•是一个基本的查找替换程序。可以从标准输入(如命令管道)读入文本,并将结果输出到标准输出(屏幕);该命令采用正则表达式进行搜索。不要和shell中的通配符相混淆。比如将ubuntu替换为Ubuntu:cattext.file|sed's/ubuntu/Ubuntu/'newtext.file•awk•用来提取文本文件中的字段。缺省的字段分割符是空格,可以使用-F指定其它分割符。catfile.txt|awk-F,'{print$1,$3,$5}',这里我们使用,作为字段分割符,同时打印第一和第三个字段。如果该文件内容为AdamBor,34,IndiaKerryMiller,22,USA,则上述命令的输出为:AdamBor,IndiaKerryMiller,USA管道,重定向和backtick•尽管这些都不是系统命令,不过它们扮演着相当重要的角色。•道(|)将一个命令的输出作为另外一个命令的输入•grephellofile.txt|wc-l•上述命令会在file.txt中搜索包含有”hello”的行并计算行数,这里grep命令的输出成了wc命令的输入。重定向•将命令的结果输出到文件,而不是标准输出(屏幕)•写入文件并复盖旧文件•加到文件的尾部,保留旧文件内容反短斜线•反短斜线可以将一个命令的输出作为其它命令的命令行参数。•find.-mtime-1-typef-print•上述命令可以查找过去24小时(-mtime–2则表示过去48小时)内修改过的文件。如果你想将上述命令查找到的所有文件打包,则可以使用如下脚本:•#!/bin/sh•#Theticksarebackticks(`)notnormalquotes('):•tar-zcvflastmod.tar.gz`find.-mtime-1-typef-print`Ubuntu•Shell里的流程控制if语句•if表达式如果条件为真,则执行then后的部分:•if....;then•....•elif....;then•....•else•....•fi•大多数情况下,可以使用测试命令来对条件进行测试,比如可以比较字符串、判断文件是否存在及是否可读等等……通常用[]来表示条件测试,注意这里的空格很重要,要确保方括号前后的空格。•[-fsomefile]:判断是否是一个文件•[-x/bin/ls]:判断/bin/ls是否存在并有可执行权限•[-n$var]:判断$var变量是否有值•[$a=$b]:判断$a和$b是否相等•执行mantest可以查看所有测试表达式可以比较和判断的类型。•下面是一个简单的if语句:•#!/bin/sh•if[$SHELL=/bin/bash];then•echoyourloginshellisthebash(bourneagainshell)•else•echoyourloginshellisnotbashbut$SHELL•fi•变量$SHELL包含有登录shell的名称,我们拿它和/bin/bash进行比较以判断当前使用的shell是否为bash。&&和||操作符•[-f/etc/shadow]&&echoThiscomputerusesshadowpasswords•这里的&&就是一个快捷操作符,如果左边的表达式为真则执行右边的语句,你也可以把它看作逻辑运算里的与操作。上述脚本表示如果/etc/shadow文件存在,则打印”Thiscomputerusesshadowpasswords”。同样shell编程中还可以用或操作(||),例如:•#!/bin/sh•mailfolder=/var/spool/mail/james•[-r$mailfolder]||{echoCannotread$mailfolder;exit1;}•echo$mailfolderhasmailfrom:•grep^From$mailfolder•该脚本首先判断mailfolder是否可读,如果可读则打印该文件中的From一行。如果不可读则或操作生效,打印错误信息后脚本退出。需要注意的是,这里我们必须使用如下两个命令:•-打印错误信息•-退出程序•我们使用花括号以匿名函数的形式将两个命令放到一起作为一个命令使用;普通函数稍后再作说明。即使不用与和或操作符,我们也可以用if表达式完成任何事情,但是使用与或操作符会更便利很多。case语句•case表达式可以用来匹配一个给定的字符串,而不是数字(可别和C语言里的switch...case混淆)。•case...in•...)dosomethinghere;;•esac•让我们看一个例子,file命令可以辨别出一个给定文件的文件类型,如:filelf.gz,其输出结果为:•lf.gz:gzipcompresseddata,deflated,originalfilename,•lastmodified:MonA