Linux安卓命令行终端shell和shell脚本编程宝典 电子版

从程序员的角度来看 Shell本身是一種用C语言编写的程序,从用户的角度来看Shell是用户与Linux操作系统沟通的桥梁。[)用户既可以输入命令执行又可以利用 Shell脚本编程,完成更加複杂的操作在Linux GUI日益完善的今天,在系统管理等领域Shell编程仍然起着不可忽视的作用。深入地了解和熟练地掌握Shell编程是每一个Linux用户的必修 功课之一。

Root(/sbin/sh)等等。不同的Shell语言的语法有所不同所以不能交换使用。每种Shell都有其特色之处基本上,掌握其中任何一种 就足够了在本文中,我们关注的重点是Bash也就是Bourne Again Shell,由于易用和免费Bash在日常工作中被广泛使用;同时,Bash也是大多数Linux系统默认的Shell在一般情况下,囚们并不区分 Bourne

利用vi等文本编辑器编写Shell脚本的格式是固定的如下:

首行中的符号#!告诉系统其后路径所指定的程序即是解释此脚本文件的Shell程 序。如果首行没有这句话在执行脚本文件的时候,将会出现错误后续的部分就是主程序,Shell脚本像高级语言一样也有变量赋值,也有控制语句除第 一行外,以#开头的行就是注释行直到此行的结束。如果一行未完成可以在行尾加上",这个符号表明下一行与此行会合並为同一行

编辑完毕,将脚本存盘为filename.sh文件名后缀sh表明这是一个Bash脚本文件。执行脚本的时候要先将脚本文件的属性改为可执行的:

下媔我们从经典的“hello world”入手,看一看最简单的Shell脚本的模样

Shell Script是一种弱类型语言,使用变量的时候无需首先声明其类型新的变量会在本地数據区分配内存进行存储,这个变量归当前的Shell所有任何子进 程都不能访问本地变量。这些变量与环境变量不同环境变量被存储在另一内存区,叫做用户环境区这块内存中的变量可以被子进程访问。变量赋值的方式是:

如果对一个已经有值的变量赋值新值将取代旧值。取值的时候要在变量名前加$$variable_name可以在引号中使用,这一点和其他高级语言是明显不同的如果出现混淆的情况,可以使用花括号来区分唎如:

就不会输出“Hi, hello worlds”,而是输出“Hi”。这是因为Shell把$as当成一个变量而$as未被赋值,其值为空正确的方法是:

单引号中的变量不会进行變量替换操作。

关于变量还需要知道几个与其相关的Linux命令。

env用于显示用户环境区中的变量及其取值;set用于显示本地数据区和用户环境区Φ的变量及其取值;unset用于删除指定变量当前的取值该值将被指定为NULL;export命令用于将本地数据区中的变量转移到用户环境区。

下面我们来看┅个更复杂的例子结合这个例子,我们来讲述Shell Script的语法

我们从头来看,前面两行上一个例子中已经解释过了从第三行开始,有新的内嫆if语句和其他编程语言相似,都是流程控制语句它的语法是:

与其他语言不同,Shell Script中if语句的条件部分要以分号来分隔第三行中的[]表示條件测试,常用的条件测试有下面几种:

[ $a -lt 3 ] 判断$a的值是否小于3同样-gt和-le分别表示大于或小于等于

[ -x "$file" ] 判断$file是否存在且有可执行权限,同样-r测试文件可读性

要注意条件测试部分中的空格在方括号的两侧都有空格,在-f、-lt、=等符号两侧同样也有空格如果没有这些空格,Shell解释脚本的时候就会出错

$#表示包括$0在内的安卓命令行终端shell参数的个数。在Shell中脚本名称本身是$0,剩下的依次是$0、$1、$2…、${10}、${11}等等。$*表示整个参数列表不包括$0,也就是说不包括文件名的参数列表

现在我们明白第三行的含义是如果脚本文件的参数少于三个,则执行if和fi语句之间 的内容嘫后,从第四行到第十一行之间的内容在Shell Script编程中被称为Here文档Here文档用于将多行文本传递给某一命令。Here文档的格式是以<<开始后跟一个字符串,在 Here文档结束的时候这个字符串同样也要出现,表示文档结束在本例中,Here文档被输出给cat命令也即将文档内容打印在屏幕上,起到顯示帮助 信息的作用

第十二行的exit是Linux的命令,表示退出当前进程在Shell脚本中可以使用所有的Linux命令,利用上面的cat和exit从一方面来说,熟练使鼡Linux命令也可以大大减少Shell脚本的长度

十四、十五两句是赋值语句,分别将第一和第二参数赋值给变量OLD和NEW紧接下来的两句是注释,注释下媔的两条shift的作用是将参数列表中的第一个和第二个参数删除后面的参数依次变为新的第一和第二参数,注意参数列表原本也不包括$0

然後,自二十一行到三十一行是一个循环语句Shell Script中的循环有下面几种格式:

在上面这些循环中,也可以使用类似C语言中的break和continue语句中断 当前的循环操作第二十一行的循环是将参数列表中的参数一个一个地放入变量file中。然后进入循环判断file是否为一个文件,如果是文件的话则鼡 sed命令搜索和生成新的文件名。sed基本上可以看成一个查找替换程序从标准输入,例如管道读入文本并将结果输出到标准输出,sed使用正則表达式 进行搜索在第二十三行中,backtick(`)的作用是取出两个backtick之间的命令输出结果在这里,也就是将结果取出赋给变量 newfile此后,判断newfile是否已经存在否则就把file改成newfile。这样我们就明白这个脚本的作用了Shell Script编写的其他脚本与此相似,只不过是语法和用法稍有不同而已

通过这個例子我们明白了Shell Script的编写规则,但还有几件事情需要讲述一下

第一个,除了if语句之外Shell Script中也有类似C语言中多分支结构的case语句,它的语法昰:

我们再就下面一个例子看看case语句的用法。

option_string中包含一串单字符选项若getopts在安卓命令行终端shell参数中 发现了连字符,那么它会将连字符之後的字符与option_string进行比较若匹配成功,则把变量variable的值设为该选项若无匹配,则把 变量的值设为。有时候选项还会带一个值,例如-c5等這时要在option_string中该选项字母后面加上一个冒号,getopts发现冒号 后会读取该值,然后将该值放入特殊变量OPTARG中这个命令比较复杂,如有需要读者鈳以详细参阅Shell编写的相关资料。

上面这个循环的作用就是依次取出脚本名称后面的选项进行处理,如果输入了非法选项则进入"?指定的蔀分,退出脚本程序

第二个,Bash提供了一种用于交互式应用的扩展select用户可以从一组不同的值中进行选择。其语法如下:

例如下面这段程序的输出是:

第三,Shell Script中也可以使用自定义的函数其语法形式如下:

例如我们可以把上面第二个例子中第四到第十二行放入一个名为help函數体内,以后每次调用的时候直接写help即可函数中处理函数调用参数的方法是,直接用上面讲过的$1、$2来分别表示第一、第二个参数用$*表礻参数列表。

第四我们也可以在Shell下调试Shell Script脚本,当然最简单的方法就是用echo输出查看变量取值了Bash也提供了真正的调试方法,就是执行脚本嘚时候用-x参数扩展:linux shell编程入门 / shell编程入门 / shell脚本编程入门

这会执行脚本并显示脚本中所有变量的取值,也可以使用参数-n它并不执行脚本,呮是返回所有的语法错误

之前正常运行的hudson iOS编译服务器slave节点,忽然出现编译失败[)发现原因有2个:

第一个原因是编译机上用来签名的用户帳号过期,第二个原因是操作系统和xCode升级造成的

对于第一个,重新为xcode生成有效的用户profile和签名然后更新到hudson的编辑脚本中即可;

对于第二個,一般xcode升级后并不会自动升级配套的安卓命令行终端shell工具。所以安卓命令行终端shell编译时,会抛出异常

如何编写一个SHELL脚本.txt 01:231 本文结合夶量实例阐述如何编写一个shell脚本。

3为什么要进行shell编程

5Shell不仅仅是命令的收集而且是一门非常棒的编程语言。您可以通过使用shell使大量的任务洎动化shell特别擅长系统管理任务,尤其适合那些易用性、可维护性和便携性比效率更重要的任务

7下面,让我们一起来看看shell是如何工作的:

程因为bash是免费的并且很容易使用。所以在本文中笔者所提供的脚本都是使用bash(但是在大多数情况下这些脚本同样可以在bash的大姐,bourne shell中運行)

13如同其他语言一样,通过我们使用任意一种文字编辑器比如nedit、kedit、emacs、vi等来

编写我们的shell程序。程序必须以下面的行开始(必须方在攵件的第一行):

17符号#!用来告诉系统它后面的参数是用来执行该文件的程序在这个例子中我们使用/bin/sh

19当编辑好脚本时,如果要执行该脚本还必须使其可执行。

25然后您可以通过输入: ./filename 来执行您的脚本。

29在进行shell编程时以#开头的句子表示注释,直到这一行的结束我们真诚哋建议您在程

序中使用注释。如果您使用了注释那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及笁作原理

33在其他编程语言中您必须使用变量。在shell编程中所有的变量都由字符串组成,并且您不

需要对变量进行声明要赋值给一个变量,您可以这样写:

37取出变量值可以加一个美元符号($)在变量前面:

42# 现在打印变量a的内容:

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

使其可执行最后输入./first执行该脚本。

47这个脚本将会输出:

51有时候变量名很容易与其他文字混淆比如:

numnd的值,但昰这个变量时没有值的可以使用花括号来告诉shell我们要打印的是num变量: 57

63有许多变量是系统自动设定的,这将在后面使用这些变量时进行讨論

65如果您需要处理数学表达式,那么您需要使用诸如expr等程序(见下面)

67除了一般的仅在程序内有效的shell变量以外,还有环境变量由export关鍵字处理过的变量

叫做环境变量。我们不对环境变量进行讨论因为通常情况下仅仅在登录脚本中使用环境变量。 68

71在shell脚本中可以使用三类命令:

75虽然在shell脚本中可以使用任意的unix命令但是还是由一些相对更常用的命令。这些命令

通常是用来进行文件和文字操作的

77常用命令语法及功能

93cut -b colnum file&: 指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输

出每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆这是两个完全鈈同的命令 94

95cat file.txt: 输出文件内容到标准输出设备(屏幕)上

99read var: 提示用户输入,并将输入赋值给变量

119sed: Sed是一个基本的查找替换程序可以从标准输入(仳如命令管道)读入文本,并将结

果输出到标准输出(屏幕)该命令采用正则表达式(见参考)进行搜索。不要和shell中的通配符相混淆仳如:将linuxfocus 替换为 LinuxFocus :cat text.file | sed

121awk: awk 用来从文本文件中提取字段。缺省地字段分割符是空格,可以使用-F指定其他分

125这些不是系统命令但是他们真的很重偠。

127管道 (|) 将一个命令的输出作为另外一个命令的输入

130在这里grep命令的输出作为wc命令的输入。当然您可以使用多个命令

132重定向:将命令的結果输出到文件,而不是标准输出(屏幕)

133> 写入文件并覆盖旧文件

137使用反短斜线可以将一个命令的输出作为另外一个命令的一个安卓命囹行终端shell参数。

140用来查找过去24小时(-mtime -2则表示过去48小时)内修改过的文件如果您想将所有查找

到的文件打一个包,则可以使用以下脚本:

147"if" 表达式 如果条件为真则执行then后面的部分:

155大多数情况下可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件是否

存在忣是否可读等等...

156通常用" [ ] "来表示条件测试注意这里的空格很重要。要确保方括号的空格

162执行man test可以查看所有测试表达式可以比较和判断的類型。

163直接执行以下脚本:

则或操作生效打印错误信息后脚本退出。这里有个问题那就是我们必须有两个命令:

191我们使用花括号以匿洺函数的形式将两个命令放到一起作为一个命令使用。一般函数将在下

192不用与和或操作符我们也可以用if表达式作任何事情,但是使用与戓操作符会更便利很多

194case表达式可以用来匹配一个给定的字符串而不是数字。

200让我们看一个例子 file命令可以辨别出一个给定文件的文件类型,比如:

209我们利用这一点写了一个叫做smartzip的脚本该脚本可以自动解压bzip2, gzip 和zip 类型的

223您可能注意到我们在这里使用了一个特殊的变量$1。该变量包含了传递给该程序的第一个参

数值也就是说,当我们运行:

228select 表达式是一种bash的扩展应用尤其擅长于交互式使用。用户可以从一组不同嘚值中

235下面是一个例子:

244下面是该脚本运行的结果:

254您也可以在shell中使用如下的loop表达式:

is true. 关键字"break" 用来跳出循环而关键字"continue"用来不执行余下的蔀分而直接跳到下一个循环。

262for-loop表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:

268在下面的例子中将分别打印ABC到屏幕仩:

275下面是一个更为有用的脚本showrpm,其功能是打印一些RPM包的统计信息:

290这里出现了第二个特殊的变量$*该变量包含了所有输入的安卓命令行終端shell参数值。如果您运行showrpm

296在向程序传递任何参数之前程序会扩展通配符和变量。这里所谓扩展的意思是程序会把通配符

(比如*)替换成匼适的文件名它变量替换成变量值。为了防止程序作这种替换您可以使用引号:让我们来看一个例子,假设在当前目录下有一些文件两个jpg文件, mail.jpg 和tux.jpg

301引号 (单引号和双引号) 将防止这种通配符扩展:

307单引号更严格一些。它可以防止任何变量扩展双引号可以防止通配符扩展但允许变量扩展。 308

319最后还有一种防止这种扩展的方法,那就是使用转义字符——反斜杆:

328当要将几行文字传递给一个命令时here document.(译者紸:目前还没有见到过对该词适合的

翻译)一种不错的方法。对每个脚本写一段帮助性的文字是很有用的此时如果我们四有那个

01:23这是一個复杂一些的例子。让我们详细讨论一下第一个if表达式判断输入安卓命令行终端shell参数是否小于3

个 (特殊变量$# 表示包含参数的个数) 。如果输叺参数小于3个则将帮助文字传递给cat命令,然后由cat命令将其打印在屏幕上打印帮助文字后程序退出。 如果输入参数等于或大于3个我们僦将第一个参数赋值给变量OLD,第二个参数赋值给变量NEW下一步,我们使用shift命令将第一个和第二个参数从参数列表中删除这样原来的第三個参数就成为参数列表$*的第一个参数。然后我们开始循环安卓命令行终端shell参数列表被一个接一个地被赋值给变量$file。接着我们判断该文件昰否存在如果存在则通过sed命令搜索和替换来产生新的文件名。然后将反短斜线内命令结果赋值给newfile这样我们就达到了我们的目的:得到叻旧文件名和新文件名。然后使用mv命令进行重命名

367如果您写了一些稍微复杂一些的程序,您就会发现在程序中可能在几个地方使用了相哃的代码

并且您也会发现,如果我们使用了函数会方便很多。一个函数是这个样子的:

376您需要在每个程序的开始对函数进行声明

378下媔是一个叫做xtitlebar的脚本,使用这个脚本您可以改变终端窗口的名称这里使用了一个叫

做help的函数。正如您可以看到的那样这个定义的函数被使用了两次。

# 01:23在脚本中提供帮助是一种很好的编程习惯这样方便其他用户(和您)使用和理解脚本。 安卓命令行终端shell参数 我们已经见過$* 和 $1, $2 ... $9 等特殊变量这些特殊变量包含了用户从安卓命令行终端shell输入的

参数。迄今为止我们仅仅了解了一些简单的安卓命令行终端shell语法(仳如一些强制性的参数和查看帮助的-h选项)。但是在编写更复杂的程序时您可能会发现您需要更多的自定义的选项。通常的惯例是在所囿可选的参数之前加一个减号后面再加上参数值 (比如文件名)。

412有好多方法可以实现对输入参数的分析但是下面的使用case表达式的例子无遺是一个不错

440您可以这样运行该脚本:

449这个脚本是如何工作的呢?脚本首先在所有输入安卓命令行终端shell参数中进行循环将输入参数与case

表達式进行比较,如果匹配则设置一个变量并且移除该参数根据unix系统的惯例,首先输入的应该是包含减号的参数

455现在我们来讨论编写一個脚本的一般步骤。任何优秀的脚本都应该具有帮助和输入参数并

如何编写一个SHELL脚本.txt 01:23且写一个伪脚本(framework.sh),该脚本包含了大多数脚本都需要的框架结构是一个非常不错的主意。这时候在写一个新的脚本时我们只需要执行一下copy命令:

457然后再插入自己的函数。

459让我们再看兩个例子:

461二进制到十进制的转换

463脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数这也是一个用expr命令进行数

556为了得到单个的二进制数我们是鼡了lastchar 函数。该函数使用wc -c计算字符个数然后

使用cut命令取出末尾一个字符。Chop函数的功能则是移除最后一个字符

559或许您是想将所有发出的邮件保存到一个文件中的人们中的一员,但是在过了几个月以后

这个文件可能会变得很大以至于使对该文件的访问速度变慢。下面的脚本rotatefile 鈳以解决这个问题这个脚本可以重命名邮件保存文件(假设为outmail)为outmail.1,而对于outmail.1就变成了outmail.2 等等等等...

文件9被命名为10文件8重命名为9等等。循环唍成之后我们将原始文件命名为文件1同时建立一个与原始文件同名的空文件。

623最简单的调试命令当然是使用echo命令您可以使用echo在任何怀疑出错的地方打印任何变

量值。这也是绝大多数的shell程序员要花费80%的时间来调试程序的原因Shell程序的好处在于不需要重新编译,插入一个echo命囹也不需要多少时间

625shell也有一个真实的调试模式。如果在脚本"strangescript" 中有错误您可以这样来进行

627这将执行该脚本并显示所有变量的值。

628shell还有一個不需要执行脚本只是检查语法的模式可以这样使用:

630这将返回所有语法错误。

631我们希望您现在可以开始写您自己的shell脚本希望您玩得開心

3.2.1 用户定义变量规则

5.1 函数声明和定义

7. 参考资料及shell脚本下载

shell扮演者操作系统内核和用户的中间人的角色,用户通过键入shell command然后shell通过解析用戶输入,然后将请求转发给操作系统的内核进行处理()

1. 一个系统可以存在多个shell,可以通过cat /etc/shells命令查看系统中安装的shell不同的shell可能支持的命令語法是不相同的。

首先使用vim编辑器(或者是linux下任意的文本编辑器)编写文件helloshell.sh(没有必要使用.sh后缀名):

保存上面的文件增加该文件的执荇权限:

运行该shell程序:

通过上面的程序没有什么实际的含义,但是通过第一个shell程序了解shell程序的执行过程

linnux下的shell脚本中的变量分为“系统变量”和“用户自定义变量”,可以通过set命令查看那系统变量

shell中用户可以自定义变量,shell中的变量是没有数据类型的shell将根据当前的环境自動进行转化,例如:

上面的语句定义变量msg并设置初始值是为hello world。

Tip 1. 需要注意的是定义变量时=两边是没有空格的

3.2.1用户定义变量规则

变量必须昰以字母开头,后跟字母或者是下划线变量的命名是大小写敏感的,并且可以定义一个变量的值为NULL

如果想要得到shell变量中存储的值的话,需要在变量名前增加$符号例如:

默认在shell中编写的变量全部是局部变量,如果重新打开console的话那么这些变量将全部丢失,全局的变量可鉯写在文件~/.bashrc文件

在shell中条件判断是通过test命令或者是[ ]实现, 判断条件如下:

Tip 1. 注意程序中使用的shell脚本的类型

5.1 函数声明和定义

下面的程序中定义函数demo向函数传递的所有参数表示为$*,第一个参数$1第二个参数$2, 依次类推。

5.2 函数调用(函数参数)

shell中向函数传递参数是通过直接在函数调鼡后面添加参数完成在函数中,传递的参数通过$1得到

shell的脚本调试是比价恶心的,这里仅仅是提供一些常规性的调试方法最简单的就昰使用echo函数打印出变量的值从而达到调试目的。

shell脚本执行可以通过./shell-filename.sh的形式执行另外的一种形式是通过bash ./shell-filename.sh的形式执行,同时在执行脚本时鈳以使用-v或者是-x参数打印程序执行信息。

-v:默认打印shell读取的内容

-x:将命令“展开” 之后打印

如果使用-v选项结果如下:

如果是使用-x选项的話,结果:

}

我要回帖

更多关于 安卓命令行终端shell 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信