《shell基础编程实例讲解.pdf》由会员分享,可在线阅读,更多相关《shell基础编程实例讲解.pdf(349页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、一些一些 shell 编程的例子编程的例子 Example 2-1 清除:清除/var/log 下的 log 文件#Start Script#Cleanup#当然要使用 root 身份来运行这个脚本 cd/var/log cat/dev/null messages cat/dev/null wtmp echo Logs cleaned up.#End Script#Example 2-2 清除:一个改良的清除脚本#Start Script#!/bin/bash#一个 Bash 脚本的正确的开头部分.#Cleanup,版本 2#当然要使用 root 身份来运行.#在此处插入代码,来打印错误消息,
2、并且在不是 root 身份的时候退出.LOG_DIR=/var/log#如果使用变量,当然比把代码写死的好.cd$LOG_DIR cat/dev/null messages cat/dev/null wtmp echo Logs cleaned up.exit#这个命令是一种正确并且合适的退出脚本的方法.#End Script#Example 2-3.cleanup:一个增强的和广义的删除 logfile 的脚本#Start Script#!/bin/bash#清除,版本 3#Warning:#-#这个脚本有好多特征,这些特征是在后边章节进行解释的,大概是进行到本书的一半的#时候,#你就会觉得
3、它没有什么神秘的了.#LOG_DIR=/var/log ROOT_UID=0#$UID 为 0 的时候,用户才具有根用户的权限 LINES=50#默认的保存行数 E_XCD=66#不能修改目录?E_NOTROOT=67#非根用户将以 error 退出#当然要使用根用户来运行 if$UID-ne$ROOT_UID then echo Must be root to run this script.exit$E_NOTROOT fi if -n$1#测试是否有命令行参数(非空).then lines=$1 else lines=$LINES#默认,如果不在命令行中指定 fi#Stephane Ch
4、azelas 建议使用下边#+的更好方法来检测命令行参数.#+但对于这章来说还是有点超前.#E_WRONGARGS=65#非数值参数(错误的参数格式)#case$1 in#)lines=50;#*!0-9*)echo Usage:basename$0 file-to-cleanup;exit$E_WRONGARGS;#*)lines=$1;#esac#*直到Loops的章节才会对上边的内容进行详细的描述.cd$LOG_DIR if pwd!=$LOG_DIR#或者 if$PWD!=$LOG_DIR#不在/var/log 中?then echo Cant change to$LOG_DIR.ex
5、it$E_XCD fi#在处理 log file 之前,再确认一遍当前目录是否正确.#更有效率的做法是#cd/var/log|#echo Cannot change to necessary directory.&2#exit$E_XCD;#tail-$lines messages mesg.temp#保存 log file 消息的最后部分.mv mesg.temp messages#变为新的 log 目录.#cat/dev/null messages#*不再需要了,使用上边的方法更安全.cat/dev/null wtmp#:wtmp 和 wtmp具有相同的作用 echo Logs clean
6、ed up.exit 0#退出之前返回 0,返回 0 表示成功.#End Script#因为你可能希望将系统 log 全部消灭,这个版本留下了 log 消息最后的部分.你将不断地找到新 的方法来完善这个脚本,并提高效率.要注意,在每个脚本的开头都使用#!,这意味着告诉你的系统这个文件的执行需要指定一个解 释器.#!实际上是一个 2 字节1的魔法数字,这是指定一个文件类型的特殊标记,换句话说,在 这种情况下,指的就是一个可执行的脚本(键入 man magic 来获得关于这个迷人话题的更多详细 信息).在#!之后接着是一个路径名.这个路径名指定了一个解释脚本中命令的程序,这个程序可 以是shell
7、,程序语言或者是任意一个通用程序.这个指定的程序从头开始解释并且执行脚本中 的命令(从#!行下边的一行开始),忽略注释.2 如:#!/bin/sh#!/bin/bash#!/usr/bin/perl#!/usr/bin/tcl#!/bin/sed-f#!/usr/awk-f 上边每一个脚本头的行都指定了一个不同的命令解释器,如果是/bin/sh,那么就是默认 shell(在 Linux 系统中默认是 Bash).3使用#!/bin/sh,在大多数商业发行的 UNIX 上,默认是 Bourne shell,这将让你的脚本可以正常的运行在非Linux机器上,虽然这将会牺牲Bash一些独特的特征.脚
8、本将与 POSIX4 的 sh 标准相一致.注意:#!后边给出的路径名必须是正确的,否则将会出现一个错误消息,通常是 Command not found,这将是你运行这个脚本时所得到的唯一结果.当然#!也可以被忽略,不过这样你的脚本文件就只能是一些命令的集合,不能够使用 shell 内建 的指令了,如果不能使用变量的话,当然这也就失去了脚本编程的意义了.注意:这个例子鼓励你使用模块化的方式来编写脚本,平时也要注意收集一些零碎的代码,这些零碎的代码可能用在你将来编写的脚本中.这样你就可以通过这些代码片段来构 造一个较大的工程用例.以下边脚本作为序,来测试脚本被调用的参数是否正确.#Start S
9、cript#E_WRONG_ARGS=65 script_parameters=-a-h-m-z#-a=all,-h=help,等等.if$#-ne$Number_of_expected_args then echo Usage:basename$0$script_parameters#basename$0是这个脚本的文件名 exit$E_WRONG_ARGS fi#End Script#Example 3-1.代码块和 I/O 重定向#Start Script#!/bin/bash#从/etc/fstab 中读行 File=/etc/fstab read line1 read line2$1
10、.test#把代码块中的所有输出都重定向到文件中 echo Results of rpm test in file$1.test#查看 rpm 的 man 页来查看 rpm 的选项 exit 0#End Script#注意:与()中的命令不同的是,中的代码块将不能正常地开启一个新 shell.2 ;路径名.一般都在 find 命令中使用.这不是一个 shell 内建命令.注意:;用来结束 find 命令序列的-exec 选项.test.test 的表达式将在中.值得注意的是是 shell 内建 test 命令的一部分,并不是/usr/bin/test 中的扩展命令 的一个连接.test.tes
11、t 表达式放在中.(shell 关键字)具体查看结构的讨论.数组元素 Array1=slot_1 echo$Array1 字符范围 在正则表达式中使用,作为字符匹配的一个范围()数学计算的扩展 在()结构中可以使用一些数字计算.具体参阅(.)结构.&filename 重定向脚本的输出到文件中.覆盖文件原有内容.command&filename 重定向 stdout 和 stderr 到文件中 command&2 重定向 command 的 stdout 到 stderr scriptname filename 重定向脚本的输出到文件中.添加到文件尾端,如果没有文件,则创建这个文件.进程替换,具
12、体见进程替换部分,跟命令替换极其类似.(command)(command)可用来做字符串比较 可用在数学计算比较 重定向,用在here document 重定向,用在here string ASCII 比较 1 veg1=carrots 2 veg2=tomatoes 3 4 if$veg1$veg2 5 then 6 echo Although$veg1 precede$veg2 in the dictionary,7 echo this implies nothing about my culinary preferences.8 else 9 echo What kind of dict
13、ionary are you using,anyhow?10 fi 正则表达式中的单词边界.如:bash$grep textfile|管道.分析前边命令的输出,并将输出作为后边命令的输入.这是一种产生命令链的 好方法.1 echo ls-l|sh 2#传递echo ls-l的输出到 shell 中,3#+与一个简单的ls-l结果相同.4 5 6 cat*.lst|sort|uniq 7#合并和排序所有的.lst文件,然后删除所有重复的行.管道是进程间通讯的一个典型办法,将一个进程的stdout放到另一个进程的stdin中.标准的方法是将一个一般命令的输出,比如cat或echo,传递到一个过滤命
14、令中(在这个 过滤命令中将处理输入),得到结果,如:cat$filename1|$filename2|grep$search_word 当然输出的命令也可以传递到脚本中.如:#Start Script#!/bin/bash#uppercase.sh:修改输出,全部转换为大写 tr a-z A-Z#字符范围必须被引用起来#+来阻止产生单字符的文件名.exit 0#End Script#Example 3-3.在后台运行一个循环#Start Script#!/bin/bash#background-loop.sh 3 for i in 1 2 3 4 5 6 7 8 9 10#第一个循环 do 6
15、 echo-n$i done在后台运行这个循环 8#在第 2 个循环之后,将在某些时候执行.echo#这个echo某些时候将不会显示.for i in 11 12 13 14 15 16 17 18 19 20#第二个循环 do echo-n$i done 16 echo#这个echo某些时候将不会显示.18#-#期望的输出应该是#1 2 3 4 5 6 7 8 9 10#11 12 13 14 15 16 17 18 19 20#然而实际的结果有可能是#11 12 13 14 15 16 17 18 19 20#1 2 3 4 5 6 7 8 9 10 bozo$#(第 2 个echo没
16、执行,为什么?)#也可能是#1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20#(第 1 个echo没执行,为什么?)#非常少见的执行结果,也有可能是:#11 12 13 1 2 3 4 5 6 7 8 9 10 14 15 16 17 18 19 20#前台的循环先于后台的执行 exit 0#Nasimuddin Ansari 建议加一句 sleep 1#+在 6 行和 14 行的 echo-n$i之后加#+将看到一些乐趣#End Script#注意:在一个脚本内后台运行一个命令,有可能造成这个脚本的挂起,等待一个按键 响应.幸运的是,我们可
17、以在 Example 11-24 附近,看到这个问题的解决办法.&与-逻辑操作.-选项,前缀.在所有的命令内如果想使用选项参数的话,前边都要加上-.COMMAND-Option1Option2.ls-al sort-dfu$filename set-$variable 1 if$file1-ot$file2 2 then 3 echo File$file1 is older than$file2.4 fi 5 6 if$a-eq$b 7 then 8 echo$a is equal to$b.9 fi 10 11 if$c-eq 24-a$d-eq 47 12 then 13 echo$c e
18、quals 24 and$d equals 47.14 fi -用于重定向 stdin 或 stdout.#Start Script#(cd/source/directory&tar cf-.)|(cd/dest/directory&tar xpvf-)#从一个目录移动整个目录树到另一个目录#courtesy Alan Cox,with a minor change#1)cd/source/directory 源目录#2)&与操作,如果 cd 命令成功了,那么就执行下边的命令#3)tar cf-.c创建一个新文档,f后边跟-指定目标文件作为 stdout#-后边的f(file)选项,指明作为
19、stdout 的目标文件.#并且在当前目录(.)执行.#4)|管道.#5)(.)一个子 shell#6)cd/dest/directory 改变当前目录到目标目录.#7)&与操作,同上.#8)tar xpvf-x解档,p保证所有权和文件属性,#v发完整消息到 stdout#f后边跟-,从 stdin 读取数据#注意:x 是一个命令,p,v,f 是选项.#Whew!#更优雅的写法应该是#cd source/directory#tar cf-.|(cd./dest/directory;tar xpvf-)#当然也可以这么写:#cp-a/source/directory/*/dest/directo
20、ry#或者:#cp-a/source/directory/*/source/directory/.*/dest/directory#如果在/source/directory 中有隐藏文件的话.#End Script#Start Script#bunzip2 linux-2.6.13.tar.bz2|tar xvf-#-未解压的 tar 文件-|-然后把它传递到tar中-#如果 tar 没能够正常的处理bunzip2,#这就需要使用管道来执行 2 个单独的步骤来完成它.#这个练习的目的是解档bzipped的 kernel 源文件.#End Script#Example 3-4.备份最后一天所有修
21、改的文件.#Start Script#!/bin/bash#在一个tarball中(经过 tar 和 gzip 处理过的文件)#+备份最后 24 小时当前目录下 d 所有修改的文件.BACKUPFILE=backup-$(date+%m-%d-%Y)#在备份文件中嵌入时间.#Thanks,Joshua Tschida,for the idea.archive=$1:-$BACKUPFILE#如果在命令行中没有指定备份文件的文件名,#+那么将默认使用backup-MM-DD-YYYY.tar.gz.tar cvf-find.-mtime-1-type f-print$archive.tar gz
22、ip$archive.tar echo Directory$PWD backed up in archive file$archive.tar.gz.#Stephane Chazelas 指出上边代码,#+如果在发现太多的文件的时候,或者是如果文件#+名包括空格的时候,将执行失败.#Stephane Chazelas 建议使用下边的两种代码之一#-#find.-mtime-1-type f-print0|xargs-0 tar rvf$archive.tar#使用 gnu 版本的 find.#find.-mtime-1-type f-exec tar rvf$archive.tar ;#对于其
23、他风格的 UNIX 便于移植,但是比较慢.#-exit 0#End Script#注意:以-开头的文件名在使用-作为重定向操作符的时候,可能会产生问题.应该写一个脚本来检查这个问题,并给这个文件加上合适的前缀.如:./-FILENAME,$PWD/-FILENAME,或$PATHNAME/-FILENAME.如果变量的值以-开头,可能也会引起问题.1 var=-n 2 echo$var 3#具有echo-n的效果了,这样什么都不会输出的.-之前工作的目录.cd-将回到之前的工作目录,具体请参考$OLDPWD环境变量.注意:一定要和之前讨论的重定向功能分开,但是只能依赖上下文区分.-算术减号.=
24、算术等号,有时也用来比较字符串.1 a=28 2 echo$a#28+算术加号,也用在正则表达式中.+选项,对于特定的命令来说使用+来打开特定的选项,用-来关闭特定的选项.%算术取模运算.也用在正则表达式中.home 目录.相当于$HOME 变量.bozo 是 bozo 的 home 目录,并且 ls bozo 将列出其中的 内容./就是当前用户的 home 目录,并且 ls/将列出其中的内容,如:bash$echo bozo /home/bozo bash$echo /home/bozo bash$echo/home/bozo/bash$echo:/home/bozo:bash$echo n
25、onexistent-user nonexistent-user+当前工作目录,相当于$PWD 变量.-之前的工作目录,相当于$OLDPWD 内部变量.=用于正则表达式,这个操作将在正则表达式匹配部分讲解,只有 version3 才支持.行首,正则表达式中表示行首.定位到行首.控制字符 修改终端或文本显示的行为.控制字符以 CONTROL+key 组合.控制字符在脚本中不能正常使用.Ctl-B 光标后退,这应该依赖于 bash 输入的风格,默认是 emacs 风格的.Ctl-C Break,终止前台工作.Ctl-D 从当前 shell 登出(和 exit 很像)EOF(文件结束符).这也能从
26、stdin 中终止输入.在console或者在xterm window中输入的时候,Ctl-D将删除光标下字符.当没有字符时,Ctrl-D将退出当前会话.在xterm window也有关闭窗口 的效果.Ctl-G beep.在一些老的终端,将响铃.Ctl-H backspace,删除光标前边的字符.如:1#!/bin/bash 2#在一个变量中插入 Ctl-H 3 4 a=HH#两个 Ctl-H(backspaces).5 echo abcdef#abcdef 6 echo-n abcdef$a#abcd f 7#注意结尾的空格 两个 twice.8 echo-n abcdef$a#abcde
27、f 9#结尾没有空格 没有 backspace 的效果了(why?).10#结果并不像期望的那样 11 echo;echo Ctl-I 就是 tab 键.Ctl-J 新行.Ctl-K 垂直 tab.(垂直 tab?新颖,没听过)作用就是删除光标到行尾的字符.Ctl-L clear,清屏.Ctl-M 回车#Start Script#!/bin/bash#Thank you,Lee Maschmeyer,for this example.read-n 1-s-p$Control-M leaves cursor at beginning of this line.Press Enter.x0d#当然
28、,0d就是二进制的回车.echo&2#-s参数使得任何输入都不将回显出来#+所以,明确的重起一行是必要的.read-n 1-s-p$Control-J leaves cursor on next line.x0a echo&2#Control-J 是换行.#read-n 1-s-p$And Control-Kx0bgoes straight down.echo&2#Control-K 是垂直制表符.#关于垂直制表符效果的一个更好的例子见下边:var=$x0aThis is the bottom linex0bThis is the top linex0a echo$var#这句与上边的例子使用
29、的是同样的办法,然而:echo$var|col#这将造成垂直制表符右边的部分在左边部分的上边.#这也解释了为什么我们要在行首和行尾加上一个换行符-#+来避免一个混乱的屏幕输出.#Lee Maschmeyer 的解释:#-#In the first vertical tab example.the vertical tab#在这里第一个垂直制表符的例子中.这个垂直制表符#+makes the printing go straight down without a carriage return.#This is true only on devices,such as the Linux con
30、sole,#+that cant go backward.#The real purpose of VT is to go straight UP,not down.#It can be used to print superscripts on a printer.#它可以用来在一个打印机上打印上标.#col 的作用,可以用来模仿 VT 的合适的行为.exit 0#End Script#Example 4-1.变量赋值和替换#Start Script#!/bin/bash#变量赋值和替换 a=375 hello=$a#-#强烈注意,在赋值的前后一定不要有空格.#如果有空格会发生什么?#如果V
31、ARIABLE=value,#+脚本将尝试运行一个VARIABLE的命令,带着一个=value参数.#如果VARIABLE=value,#+script tries to run value command with#+脚本将尝试运行一个value的命令,带着#+the environmental variable VARIABLE set to.#+一个被赋成值的环境变量VARIABLE.#-echo hello#没有变量引用,不过是个 hello 字符串 echo$hello echo$hello#同上 echo$hello echo$hello echo hello=A B C D ec
32、ho$hello#A B C D echo$hello#A B C D#就象你看到的 echo$hello 和 echo$hello 将给出不同的结果.#Quoting a variable preserves whitespace.#引用一个变量将保留其中的空白,当然,如果是变量替换就不会保留了.echo echo$hello#$hello#全引用的作用#+将导致$变成一个单独的字符.#注意两种引用不同的效果 hello=#设置为空值 echo$hello(null value)=$hello#注意设置一个变量为空,与 unset 它,不是一回事,虽然看起来一样#-#可以在同一行上设置多个变
33、量.#+要以空白分隔#小心,这会降低可读性,和可移植性.var1=21 var2=22 var3=$V3 echo echo var1=$var1 var2=$var2 var3=$var3#在老版本的sh上,可能会有问题.#-echo;echo numbers=one two three#other_numbers=1 2 3#如果变量中有空白,那么引用就必要了.#echo numbers=$numbers echo other_numbers=$other_numbers#other_numbers=1 2 3 echo echo uninitialized_variable=$unini
34、tialized_variable#Uninitialized 变量为空值(根本就没赋值).uninitialized_variable=#声明,但是没被初始化#+其实和前边设置为空值得作用是一样的.echo uninitialized_variable=$uninitialized_variable#还是一个空值 uninitialized_variable=23#赋值 unset uninitialized_variable#Unset it.echo uninitialized_variable=$uninitialized_variable#还是空值 echo exit 0#End S
35、cript#注意:一个空值变量,或者是根本就没声明的变量,在赋值之前使用它可能会引起问题.但是还是可以用来做算术运算#Start Script#echo$uninitialized#(blank line)let uninitialized+=5#Add 5 to it.echo$uninitialized#5#结论:#对于一个空值变量在做算术操作的时候,就好像它的值为 0 一样.#This is undocumented(and probably non-portable)behavior.#这并没被文档化(可能是不可移植)的行为.#End Script#Example 4-2.一般的变量赋
36、值#Start Script#!/bin/bash#裸体变量 echo#变量什么时候是裸体的,比如前边少了$的时候.#当它被赋值的时候,而不是被引用的时候.#赋值 a=879 echo The value of a is$a.#使用 let 赋值 let a=16+5 echo The value of a is now$a.echo#在 for 循环中 echo-n Values of a in the loop are:for a in 7 8 9 11 do echo-n$a done echo echo#在 read 命令状态中 echo-n Enter a read a echo T
37、he value of a is now$a.echo exit 0#End Script#Example 4-3.变量赋值,一般的和比较特殊的#Start Script#!/bin/bash a=23#Simple case echo$a b=$a echo$b#现在让我们来点小变化 a=echo Hello!#把 echo 命令的结果传给变量 a echo$a#注意,如果在命令扩展结构中使用一个(!)的话,在命令行中将不能工作#+因为这触发了 Bash 的历史机制.#但是,在校本里边使用的话,历史功能是被关闭的,所以就能够正常运行.15 a=ls-l#把 ls-l 的结果给 a echo$
38、a#别忘了,这么引用的话,ls 的结果中的所有空白部分都没了(包括换行)echo echo$a#这么引用就正常了,保留了空白#(具体参阅章节引用)exit 0#End Script#Example 4-4 整型还是 string?#Start Script#!/bin/bash#int-or-string.sh:整形还是 string?a=2334#整型 let a+=1 echo a=$a#a=2335 echo#还是整型 b=$a/23/BB#将 23 替换成 BB#这将把 b 变量从整型变为 string echo b=$b#b=BB35 declare-i b#即使使用 declare
39、 命令也不会对此有任何帮助,9.4 节有解释 echo b=$b#b=BB35 let b+=1#BB35+1=echo b=$b#b=1 echo c=BB34 echo c=$c#c=BB34 d=$c/BB/23#S 将 BB 替换成 23#这使得$d 变为一个整形 echo d=$d#d=2334 let d+=1#2334+1=echo d=$d#d=2335 echo#关于空变量怎么样?e=echo e=$e#e=let e+=1#算术操作允许一个空变量?echo e=$e#e=1 echo#空变量将转换成一个整型变量#关于未声明的变量怎么样?echo f=$f#f=let f+=
40、1#算术操作允许么?echo f=$f#f=1 echo#未声明的变量将转换成一个整型变量#所以说 Bash 中的变量都是无类型的.exit 0#End Script#Example 4-5 位置参数#Start Script#!/bin/bash#作为用例,调用这个脚本至少需要 10 个参数,如#./scriptname 1 2 3 4 5 6 7 8 9 10 MINPARAMS=10 echo echo The name of this script is$0.#添加./是为了当前目录 echo The name of this script is basename$0.#去掉目录信息,
41、具体见basename命令 echo if -n$1#测试变量被被引用 then echo Parameter#1 is$1#没被转义 fi if -n$2 then echo Parameter#2 is$2 fi if -n$3 then echo Parameter#3 is$3 fi#.if -n$10#大于 9 的参数必须出现在中.then echo Parameter#10 is$10 fi echo-echo All the command-line parameters are:$*if$#-lt$MINPARAMS#$#是传到脚本里的位置参数的个数 then echo ech
42、o This script needs at least$MINPARAMS command-line arguments!fi echo exit 0#End Script#标记法是一种很好的使用位置参数的方法.这也需要间接引用(见 Example 34-2)1 args=$#位置参数的个数 2 lastarg=$!args 3#或:lastarg=$!#4#注意 lastarg=$!$#将报错 一些脚本可能会依赖于使用不同的调用名字,而表现出不同的行为,这样一般都需要 判断$0,而其他的名字都是通过 ln 命令产生的链接.(具体参见 Example 12-2)如果脚本需要一个命令行参数,而
43、调用的时候,没用这个参数,这就有可能造成分配一个 空变量,这样估计就会引起问题.一种解决办法就是在这个位置参数,和相关的变量后 边,都添加一个额外的字符.具体见下边的例子.#Start Script#variable1_=$1_#而不是 variable1=$1#这将阻止一个错误,即使在调用时没使用这个位置参数.critical_argument01=$variable1_#这个扩展的字符是可以被消除掉的,就像这样.variable1=$variable1_/_/#副作用就是$variable1_多了一个下划线#这里使用了一个参数替换模版(后边会有具体的讨论)#(Leaving out the
44、 replacement pattern results in a deletion.)#(在一个删除动作中,节省了一个替换模式)#一个解决这种问题的更简单的做法就是,判断一下这个位置参数是否传递下来了 if -z$1 then exit$E_MISSING_POS_PARAM fi#但是上边的方法将可能产生一个意外的副作用#参数替换的更好的办法应该是:#$1:-$DefaultVal#具体察看Parameter Substition节#+在第 9 章#End Script#Example 4-6 wh,whois 节点名字查询#Start Script#!/bin/bash#ex18.sh#
45、Does a whois domain-name lookup on any of 3 alternate servers:#,#把这个脚本重命名为wh,然后放到/usr/local/bin 下#需要 3 个符号链接#ln-s/usr/local/bin/wh/usr/local/bin/wh-ripe#ln-s/usr/local/bin/wh/usr/local/bin/wh-cw#ln-s/usr/local/bin/wh/usr/local/bin/wh-radb E_NOARGS=65 if -z$1 then echo Usage:basename$0 domain-name ex
46、it$E_NOARGS fi#Check script name and call proper server.#检查脚本名字,然后调用合适的服务器 case basename$0 in#Or:case$0#*/in wh )whois$;wh-ripe)whois$;wh-radb)whois$;wh-cw )whois$;*)echo Usage:basename$0 domain-name;esac exit$?#End Script#Example 4-7 使用 shift#Start Script#!/bin/bash#使用shift来穿过所有的位置参数.#把这个脚本命名为 shft
47、,#+并且使用一些参数来调用它,如:#./shft a b c def 23 skidoo until -z$1#知道所有参数都用光 do echo-n$1 shift done echo#额外的换行.exit 0#End Script#Example 5-1 echo 一些诡异的变量#Start Script#!/bin/bash#weirdvars.sh:echo 诡异的变量 var=($echo$var#($echo$var#($并没有什么不同 echo IFS=echo$var#($转换成空格了?明显和 IFS 有关系么!又不傻!echo$var#($exit 0#End Script
48、#Example 5-2 转义符#Start Script#!/bin/bash#escaped.sh:转义符 echo;echo echo vvvv#逐字的打印vvvv.#使用-e 选项的 echo 命令来打印转义符 echo=echo VERTICAL TABS echo-e vvvv#Prints 4 vertical tabs.echo=echo QUOTATION MARK echo-e 042#打印(引号,8 进制的 ASCII 码就是 42).echo=#The$X construct makes the-e option unnecessary.#如果使用$X结构,那-e 选项
49、就不必要了 echo;echo NEWLINE AND BEEP echo$n#新行.echo$a#Alert(beep).echo=echo QUOTATION MARKS#版本 2 以后 Bash 允许使用$nnn结构#注意这种情况,nnn是 8 进制 echo$t 042 t#Quote()framed by tabs.#当然,也可以使用 16 进制的值,使用$xhhh 结构 echo$t x22 t#Quote()framed by tabs.#早一点的 Bash 版本允许x022这种形式 echo=echo#分配 ASCII 字符到变量中#-quote=$042#042 是,分配到变量中 echo$quote This is a quoted string,$quote and this lies outside the quotes.echo#Concatenating ASCII chars in a variable.#变量中的连续的 ASCII char.triple_underline=$137137137#137 是 8 进制的 ASCII 码_.echo$triple_underline UNDERLINE$triple_underline echo ABC=$101102103010#101,102,103 是 8 进制的码 A,B,C.echo$ABC
限制150内