欢迎各位的光临,鄙人以好酒好菜招待~~!!^_^

BASH shell

上一篇 / 下一篇  2007-05-27 19:58:07

 
非常好的BASH脚本编写教程
*X2L1oV~h0
"lv#s#A-V\0这里有个老American写的 BASH脚本编写教程,非常不错,至少没接触过BASH的也能看懂!
TP6{(H3g2H0Linux宝库$^4Xf%zX s0m
建立一个脚本
7X V;H8^ie/B)@0Linux宝库b(l WbN,M
  Linux中有好多中不同的shell,但是通常我们使用bash (bourne again shell) 进行shell编程,因为bash是免费的并且很容易使用。所以在本文中笔者所提供的脚本都是使用bash(但是在大多数情况下,这些脚本同样可以在 bash的大姐,bourne shell中运行)。Linux宝库]3k&}1c?p&KV\r
  如同其他语言一样,通过我们使用任意一种文字编辑器,比如nedit、kedit、emacs、viLinux宝库G"D8@Z o MB2bl
  等来编写我们的shell程序。
.cY,p4t"X!Sa0  程序必须以下面的行开始(必须方在文件的第一行):
*]3BKf z%S4\0#!/bin/shLinux宝库B teM_
  符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。Linux宝库 d5{Erw l
  当编辑好脚本时,如果要执行该脚本,还必须使其可执行。
;d(NV.Cx2?Mq5k J!l0  要使脚本可执行:Linux宝库ECNXu,s'I+^c
chmod +x filename
seCg&v2aa;w L0  然后,您可以通过输入: ./filename 来执行您的脚本。Linux宝库bds.Z#U}we8@
注释Linux宝库}T"xu1j6T-X
  在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程序中使用注释。如果您使用了注释,那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及工作原理。Linux宝库 O*xfJ8u.Z9v%Y
变量
1h ad i!W[I0  在其他编程语言中您必须使用变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:Linux宝库/k]ds]m2^*{$@
变量名=值
Z$um0ri0I$S0  取出变量值可以加一个美元符号($)在变量前面:
K,f8Z9~c7g0#!/bin/shLinux宝库Il:N8yvt6d
#对变量赋值:Linux宝库 DluugqS5S$i
a="hello world"Linux宝库cW-_c"U$J&AD
# 现在打印变量a的内容:
:_^&^.[!@iu0echo "A is:"
:NJQV`0echo $a
hn4]%df t C+s0  在您的编辑器中输入以上内容,然后将其保存为一个文件first。之后执行chmod +x firstLinux宝库p7P$qb.{9I+?0GiS$Q
  使其可执行,最后输入./first执行该脚本。Linux宝库#Vk~,tOh4s
  这个脚本将会输出:
1g_ J2jy:Xv*Xg5v0A is:Linux宝库"I,J,V _@"lHR
hello worldLinux宝库_*]rTO
  有时候变量名很容易与其他文字混淆,比如:
Q2LLfpp0num=2
WF U/DV-^(iI0echo "this is the $numnd"
t,t].Zr%BR0  这并不会打印出"this is the 2nd",而仅仅打印"this is the ",因为shell会去搜索变量numnd的值,但是这个变量时没有值的。可以使用花括号来告诉shell我们要打印的是num变量:Linux宝库:rj:^*R kZtb*K
num=2Linux宝库/nM!v5K\8L8U&v*@
echo "this is the ${num}nd"Linux宝库?:A7}b#~4ix
  这将打印: this is the 2ndLinux宝库*f.d}Vkv4M+j
  有许多变量是系统自动设定的,这将在后面使用这些变量时进行讨论。Linux宝库q&{-{ H }2b N$J#|e
  如果您需要处理数学表达式,那么您需要使用诸如expr等程序(见下面)。Linux宝库%e*Ql {p7D6\
  除了一般的仅在程序内有效的shell变量以外,还有环境变量。由export关键字处理过的变量叫做环境变量。我们不对环境变量进行讨论,因为通常情况下仅仅在登录脚本中使用环境变量。Linux宝库!lg#lj v$|7jy2S
Shell命令和流程控制
\~pk%v7CwAd0  在shell脚本中可以使用三类命令:
|F_)ku#^R"P01)Unix 命令:
tP0\;DC9{"F2C0  虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令。这些命令通常是用来进行文件和文字操作的。Linux宝库a(Mh9DC ?;_ZB
常用命令语法及功能Linux宝库.tE v h0j(f l3YeY1A| p
  echo "some text": 将文字内容打印在屏幕上
%j0C*AZ6] B(fCgw4bL0  ls: 文件列表
N*I!kku0  wc –l filewc -w filewc -c file: 计算文件行数计算文件中的单词数计算文件中的字符数Linux宝库"u1P!L0?#VC!@2A
  cp sourcefile destfile: 文件拷贝Linux宝库4V9z#L&ko-j/f
  mv oldname newname : 重命名文件或移动文件Linux宝库GO {CJ X"MT;s
  rm file: 删除文件
S h,u ~2I N#H)A0  grep 'pattern' file: 在文件内搜索字符串比如:grep 'searchstring' file.txt
'\7lW_v;[yn0  cut -b colnum file: 指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输出每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆,这是两个完全不同的命令Linux宝库!dyz n[;[:rI9T K
  cat file.txt: 输出文件内容到标准输出设备(屏幕)上
1g'jT!Omk0  file somefile: 得到文件类型
pFOS y0  read var: 提示用户输入,并将输入赋值给变量Linux宝库fm }^zl+\ B
  sort file.txt: 对file.txt文件中的行进行排序Linux宝库W;M I%j%z,m%_1~;\N!R
  uniq: 删除文本文件中出现的行列比如: sort file.txt | uniqLinux宝库7wg9B&Kw e8t|b:TO
  expr: 进行数学运算Example: add 2 and 3expr 2 "+" 3Linux宝库V].f6q)o!thpyKe$_
  find: 搜索文件比如:根据文件名搜索find . -name filename -printLinux宝库wQaq je R2Z
  tee: 将数据输出到标准输出设备(屏幕) 和文件比如:somecommand | tee outfile
{ F| | VG f:b F0  basename file: 返回不包含路径的文件名比如: basename /bin/tux将返回 tuxLinux宝库`8Q&A} ^
  dirname file: 返回文件所在路径比如:dirname /bin/tux将返回 /binLinux宝库)S,\[U$|)g`ul
  head file: 打印文本文件开头几行Linux宝库*cU$op M0d9am@/P
  tail file : 打印文本文件末尾几行Linux宝库F9g(jx@zV,o#\
  sed: Sed是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,并将结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。不要和shell中的通配符相混淆。比如:将linuxfocus 替换为 LinuxFocus :cat text.file | sed 's/linuxfocus/LinuxFocus/' > newtext.file
*jbt%}\;P(g#C#L0  awk: awk 用来从文本文件中提取字段。缺省地,字段分割符是空格,可以使用-F指定其他分割符。cat file.txt | awk -F, '{print $1 "," $3 }'这里我们使用,作为字段分割符,同时打印第一个和第三个字段。如果该文件内容如下: Adam Bor, 34, IndiaKerry Miller, 22, USA命令输出结果为:Adam Bor, IndiaKerry Miller, USALinux宝库.OHL*OJm
2) 概念: 管道, 重定向和 backtickLinux宝库6WC"d4P"_w
  这些不是系统命令,但是他们真的很重要。
/`m.N _mC T0  管道 (|) 将一个命令的输出作为另外一个命令的输入。
7AmZ(q5H Ls0grep "hello" file.txt | wc -l
f1~eAZsFw0  在file.txt中搜索包含有”hello”的行并计算其行数。
H V6J-RX~ x&NL']+A8j0  在这里grep命令的输出作为wc命令的输入。当然您可以使用多个命令。
G-o(H2G_*r*t |k0  重定向:将命令的结果输出到文件,而不是标准输出(屏幕)。Linux宝库l gk G.G;n
  > 写入文件并覆盖旧文件
%[R/uJ-{b@,K$r [w0  >> 加到文件的尾部,保留旧文件内容。Linux宝库!_\t]:K {$fo(fO
反短斜线
t"Y!R-s+lG q0 使用反短斜线可以将一个命令的输出作为另外一个命令的一个命令行参数。Linux宝库OY"kidSV.P
  命令:Linux宝库"t(}0|@0zvh+d
find . -mtime -1 -type f -print
u8UWhJF)h0  用来查找过去24小时(-mtime –2则表示过去48小时)内修改过的文件。如果您想将所有查找到的文件打一个包,则可以使用以下脚本:Linux宝库7C$a~2RJXzj
#!/bin/sh
&yeQ4n@'S0# The ticks are backticks (`) not normal quotes ('):
y-CRW!Rs5O0tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`
.pO2S,bW8{.@0  3) 流程控制
@ A}7}xg)Q0  "if" 表达式 如果条件为真则执行then后面的部分:Linux宝库3ffeITt w
if ....; then
bJ Vja3U U`u%x!C0  ....Linux宝库 h2BMaL \2f!R7g
elif ....; thenLinux宝库#x6~9~R!t
  ....Linux宝库i~ I[3DK
else
0q?w u^H0  ....
X;VX N x F%Q+W%_0fi
OU1\"wh0  大多数情况下,可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件是否存在及是否可读等等…Linux宝库/a1uW2mcW.o#Q0W\
  通常用" [ ] "来表示条件测试。注意这里的空格很重要。要确保方括号的空格。Linux宝库)P |Tz8f}6l
[ -f "somefile" ] :判断是否是一个文件Linux宝库(u P\CPu2aErpc
[ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限
zo3RE [?z3R0[ -n "$var" ] :判断$var变量是否有值
)D3fV$sRs9JJ0[ "$a" = "$b" ] :判断$a和$b是否相等Linux宝库;ad1b c7f/Yy#O
  执行man test可以查看所有测试表达式可以比较和判断的类型。
6b+e:tZ'K0  直接执行以下脚本:Linux宝库 ESq]XDU^ d
#!/bin/sh
j/f*y-i#p!f0if [ "$SHELL" = "/bin/bash" ]; thenLinux宝库r-h7j9ghVI K
 echo "your login shell is the bash (bourne again shell)"Linux宝库(v9xx2c3H#xd}
elseLinux宝库_}sZ%EB"L/@ L2}
 echo "your login shell is not bash but $SHELL"Linux宝库:K%epO.rP c
fi
T])XEk)d @0  变量$SHELL包含了登录shell的名称,我们和/bin/bash进行了比较。
"`C!M:_9Q2ZZ0快捷操作符
$o#T:C0SDW1S/bM0  熟悉C语言的朋友可能会很喜欢下面的表达式:
E(EhBY D0[ -f "/etc/shadow" ] && echo "This computer uses shadow passwors"
0n'RIV RJ0  这里 && 就是一个快捷操作符,如果左边的表达式为真则执行右边的语句。您也可以认为是逻辑运算中的与操作。上例中表示如果/etc/shadow文件存在则打印” This computer uses shadow passwors”。同样或操作(||)在shell编程中也是可用的。这里有个例子:Linux宝库a3r oY'HQ
#!/bin/shLinux宝库%Y8xU(`Y.l7J&xL
mailfolder=/var/spool/mail/jamesLinux宝库 w8n#t d#}W O1ae
[ -r "$mailfolder" ]' '{ echo "Can not read $mailfolder" ; exit 1; }Linux宝库*@S&qhV``
echo "$mailfolder has mail from:"Linux宝库nGEM?O/C {
grep "^From " $mailfolder
b7i ]d [B"w4{ F0  该脚本首先判断mailfolder是否可读。如果可读则打印该文件中的"From" 一行。如果不可读则或操作生效,打印错误信息后脚本退出。这里有个问题,那就是我们必须有两个命令:
:HTVn,] S0  -打印错误信息
)|ll#VM V0  -退出程序
_Lb L9u F,SP0  我们使用花括号以匿名函数的形式将两个命令放到一起作为一个命令使用。一般函数将在下文提及。Linux宝库!Rf Yu X9NB i
  不用与和或操作符,我们也可以用if表达式作任何事情,但是使用与或操作符会更便利很多。Linux宝库:k(hw Sw)o#[;rA
  case表达式可以用来匹配一个给定的字符串,而不是数字。
,sW%c#pLn0case ... in
5l x:j*ZRX1g3US0...) do something here ;;Linux宝库 ` C%g;xI/a1W"g
esacLinux宝库 Af[e1q
  让我们看一个例子。 file命令可以辨别出一个给定文件的文件类型,比如:
1bb8lZ-K}F0file lf.gz
[h*g L-w,T t'eD0  这将返回:
4l2Hh0ln0lf.gz: gzip compressed data, deflated, original filename,Linux宝库-Css8u3~@5S8y
last modified: Mon Aug 27 23:09:18 2001, os: UnixLinux宝库0e\ n8eKZJ
 我们利用这一点写了一个叫做smartzip的脚本,该脚本可以自动解压bzip2, gzip 和zip 类型的压缩文件:Linux宝库t Ck!WR/J`4R^ql
#!/bin/sh
q#dn5V(?C+{5j/Zs0ftype=`file "$1"`Linux宝库G@0s4f`2RK+] i
case "$ftype" in
4lT_z)U;K0"$1: Zip archive"*)
.j4f;d3pH+g7n{A0  unzip "$1" ;;Linux宝库^E9Db^Xv
"$1: gzip compressed"*)
5k/b s2y;[3Ib0|0  gunzip "$1" ;;Linux宝库-ar0x Zs3tv
"$1: bzip2 compressed"*)
.R;`D[{i-_5O0  bunzip2 "$1" ;;Linux宝库mQ@ oh
*) error "File $1 can not be uncompressed with smartzip";;Linux宝库a-A \K7vT%_
esac
/Lo%jwLTGS2x0  您可能注意到我们在这里使用了一个特殊的变量$1。该变量包含了传递给该程序的第一个参数值。也就是说,当我们运行:
|@ Q]0PA)Mr0smartzip articles.zip
??,R Tn/Zx0$1 就是字符串 articles.zipLinux宝库?3g%{~)E5}a@0Z5{ R
  select 表达式是一种bash的扩展应用,尤其擅长于交互式使用。用户可以从一组不同的值中进行选择。Linux宝库6b^d.r.c
select var in ... ; doLinux宝库uzX%f5xGy0H~ xh
 breakLinux宝库E%Ae[9Q'G|
done
/N8Ag9Dr0.... now $var can be used ....
&m-D]!pd0下面是一个例子:Linux宝库0~$m9AaqW
#!/bin/sh
;Dq5]9Z7N[Q0echo "What is your favourite OS?"Linux宝库2Z ?'N.]l+z+Y
select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
:M{ x)d$H;GJS0    break
^6p0Jo {0doneLinux宝库-}Z0T6`UMc1y]
echo "You have selected $var"Linux宝库J5E:t~3f&N T.df(ohv
  下面是该脚本运行的结果:
Ox,sL.Q,S$f0What is your favourite OS?
`b{i-B:E01) LinuxLinux宝库&|4QaU ^ n8[9w
2) Gnu HurdLinux宝库2W~x bD
3) Free BSDLinux宝库]n@9tq#\ K
4) Other
-RrE;_4[}"Q(}.pj0#? 1Linux宝库L Gv'd0^h}}'w\Y
You have selected Linux
"~K oW+g(b3`0  您也可以在shell中使用如下的loop表达式:Linux宝库f k6k+x4oD2iO
while ...; doLinux宝库'|ZlJhZ
....
9i0Pe(q&h8ZR-Vq8A5c(p0done
1H:T7{4\ a0  while-loop 将运行直到表达式测试为真。will run while the expression that we test for is true. 关键字"break" 用来跳出循环。而关键字”continue”用来不执行余下的部分而直接跳到下一个循环。
g|9lPrqy0  for-loop表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:Linux宝库7Q jf:O!\LS|
for var in ....; doLinux宝库B8d!e.w] n~U&I8a
 ....
!?'j@9_)w_7]5D0doneLinux宝库i} y)`2L
  在下面的例子中,将分别打印ABC到屏幕上:
$Z'zF)J c0#!/bin/shLinux宝库:DqN3swS e
for var in A B C ; do
5t3xKORv-nA0 echo "var is $var"Linux宝库{Y4f:z'@`
doneLinux宝库l!v1]$v*AKM
  下面是一个更为有用的脚本showrpm,其功能是打印一些RPM包的统计信息:
vc h6~G:k0#!/bin/shLinux宝库 N5kZGH jf7|
# list a content summary of a number of RPM packagesLinux宝库Xd,F7G~ Bx
# USAGE: showrpm rpmfile1 rpmfile2 ...
&g5}o6j2No?0# EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpmLinux宝库H'`,S2@&X y4B
for rpmpackage in $*; do
Dd~o*I8Y9w0 if [ -r "$rpmpackage" ];thenLinux宝库,NzV^"m#p
  echo "=============== $rpmpackage =============="
2u(k.U'_&k0  rpm -qi -p $rpmpackage
8C6m*\ DA`o0 else
6vWKV3p"?R0  echo "ERROR: cannot read file $rpmpackage"Linux宝库{0kw9T7?)Q
 fiLinux宝库:Te/Dw*_,K-F'@ W
done
(M]:Ku W*T}B5o0  这里出现了第二个特殊的变量$*,该变量包含了所有输入的命令行参数值。如果您运行showrpm openssh.rpm w3m.rpm webgrep.rpmLinux宝库+f7fb"c.m ~
  此时 $* 包含了 3 个字符串,即openssh.rpm, w3m.rpm and webgrep.rpm.
c#t)P%BnV0引号
D[6{tIS$wz0  在向程序传递任何参数之前,程序会扩展通配符和变量。这里所谓扩展的意思是程序会把通配符(比如*)替换成合适的文件名,它变量替换成变量值。为了防止程序作这种替换,您可以使用引号:让我们来看一个例子,假设在当前目录下有一些文件,两个jpg文件, mail.jpg 和tux.jpg。Linux宝库y-MM`P
Linux宝库L1u7f bJ
#!/bin/shLinux宝库5s)sn,E0{
echo *.jpg
R6f Z qp8P0  这将打印出"mail.jpg tux.jpg"的结果。Linux宝库Q3a e,`_1o7Ti+E/~7n&d
  引号 (单引号和双引号) 将防止这种通配符扩展:Linux宝库0x G&T)bp:O ]
#!/bin/shLinux宝库T%H$p^N{ Z
echo "*.jpg"Linux宝库-U(F z6BbfBO
echo '*.jpg'Linux宝库#R9[YoAF-g rI
  这将打印"*.jpg" 两次。
6JAL LZ(B @:Uy0  单引号更严格一些。它可以防止任何变量扩展。双引号可以防止通配符扩展但允许变量扩展。
d C ~q}hS~z0#!/bin/sh
b1wOR _0echo $SHELLLinux宝库(S9gv4i:|"yu F
echo "$SHELL"Linux宝库*J,h \:K2M,}f@ Njq-?r
echo '$SHELL'Linux宝库.X.?.Wb9[ s
  运行结果为:Linux宝库 UQE E1S `Y
/bin/bashLinux宝库 i'S5\;Le-X
/bin/bashLinux宝库0^3w7j%u8hD(s.\:a%U
$SHELL
)l;? IjQ0  最后,还有一种防止这种扩展的方法,那就是使用转义字符——反斜杆:Linux宝库t}En:Q$a}\&]
echo *.jpg
4jaz nk0echo $SHELL
y;Gf-C AW/a2]~0  这将输出:
G%f|_5v&R#e}0*.jpgLinux宝库c,j4h\8Orw
$SHELLLinux宝库ra G#? F
Here documents
`Dl'D T.wQ E0  当要将几行文字传递给一个命令时,here documents(译者注:目前还没有见到过对该词适合的翻译)一种不错的方法。对每个脚本写一段帮助性的文字是很有用的,此时如果我们四有那个 here documents就不必用echo函数一行行输出。 一个 "Here document" 以 << 开头,后面接上一个字符串,这个字符串还必须出现在here document的末尾。下面是一个例子,在该例子中,我们对多个文件进行重命名,并且使用here documents打印帮助:
aQ)p5Gs&O/X8[-RV-D0#!/bin/shLinux宝库u8M2W:_-z B+UP
# we have less than 3 arguments. Print the help text:
:oR8x2cJ0oL0if [ $# -lt 3 ] ; then
)Z[(yHf2jO`3V6}0cat <Linux宝库l)Y d/T\ X
ren -- renames a number of files using sed regular expressionsLinux宝库m4G6q5e3C5H1y
USAGE: ren 'regexp' 'replacement' files...
+m;l3|{$m$j)G0EXAMPLE: rename all *.HTM files in *.html:Linux宝库'hd4?] ^x9o2eG
 ren 'HTM$' 'html' *.HTMLinux宝库V6g4}F7t
HELP
]-E6KU8M/oSVg0 exit 0
[2aL%O7y-vPk0fi
e${o{-k?0OLD="$1"
BJ+rb,]7s9In5v0NEW="$2"
;c8}(K d1lE'R0# The shift command removes one argument from the list ofLinux宝库2g4oC.]%O F(~:e
# command line arguments.
.oG_Z"C0shiftLinux宝库2e k:G1_9ZsAO%S+f
shiftLinux宝库9x[&bTF"T5X#R(a
# $* contains now all the files:
N+c;W z'O6F0j0for file in $*; do
@!uw]DEdG0  if [ -f "$file" ] ; thenLinux宝库9WcMH;f(Ap}G Q
   newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
_S2v2z Cof5K~0   if [ -f "$newfile" ]; then
K4kRVG{3h0    echo "ERROR: $newfile exists already"Linux宝库] yb"Aw |:{
   elseLinux宝库[} ItfHi
    echo "renaming $file to $newfile ..."
5}8o+G&Pt0    mv "$file" "$newfile"
#e} ^ q?+R-M&Hg0   fiLinux宝库:X!RAa*X7S
  fiLinux宝库Tu*ck0V`o#n J
doneLinux宝库e%z%o(I['G*m
  这是一个复杂一些的例子。让我们详细讨论一下。第一个if表达式判断输入命令行参数是否小于3个 (特殊变量$# 表示包含参数的个数) 。如果输入参数小于3个,则将帮助文字传递给cat命令,然后由cat命令将其打印在屏幕上。打印帮助文字后程序退出。如果输入参数等于或大于3个,我们就将第一个参数赋值给变量OLD,第二个参数赋值给变量NEW。下一步,我们使用shift命令将第一个和第二个参数从参数列表中删除,这样原来的第三个参数就成为参数列表$*的第一个参数。然后我们开始循环,命令行参数列表被一个接一个地被赋值给变量$file。接着我们判断该文件是否存在,如果存在则通过sed命令搜索和替换来产生新的文件名。然后将反短斜线内命令结果赋值给newfile。这样我们就达到了我们的目的:得到了旧文件名和新文件名。然后使用mv命令进行重命名。Linux宝库f.Ot ]:tc6n
函数
gm1bB:C[[1x(x zv0  如果您写了一些稍微复杂一些的程序,您就会发现在程序中可能在几个地方使用了相同的代码,并且您也会发现,如果我们使用了函数,会方便很多。一个函数是这个样子的:Linux宝库/I }A+z_0Sj\c)R
functionname()
R,m uv!Qm] ~0{Linux宝库$FXX&@ t6J%w7w
# inside the body $1 is the first argument given to the function
S x$_?^0# $2 the second ...Linux宝库F%CJ3xD'j
body
!Ty+Aw#j'd'S!r ]0}Linux宝库 i%F4XQNDX5h${ bQ
  您需要在每个程序的开始对函数进行声明。Linux宝库OY)^ x:i }L

|/Ad_;` ~0  下面是一个叫做xtitlebar的脚本,使用这个脚本您可以改变终端窗口的名称。这里使用了一个叫做help的函数。正如您可以看到的那样,这个定义的函数被使用了两次。
Y)u"[Zl$PR0#!/bin/sh
}B7q Y6z3w"d0# vim: set sw=4 ts=4 et:
(u/^)K[!?J^ J!~0help()Linux宝库Sr'o^2}[1TcF!{Y%N
{Linux宝库lAjc6jo Z z7y
  cat <Linux宝库 n6{lMg4yU
xtitlebar -- change the name of an xterm, gnome-terminal or kde konsoleLinux宝库e3x Hb)ni
USAGE: xtitlebar [-h] "string_for_titelbar"
W B-V+Hr}A&fX0OPTIONS: -h help textLinux宝库$Yie/M([ ^;[u;XJ}_
EXAMPLE: xtitlebar "cvs"
e,_2kS^.jb1nt0HELPLinux宝库W\'j9cdb3rE/c5K?
  exit 0
\hq#`i V#U*H0}Linux宝库YU8`/A/n]4]2e
# in case of error or if -h is given we call the function help:Linux宝库 f*|g As\Aa-E
[ -z "$1" ] && help
P"]H+~ {3h0[ "$1" = "-h" ] && helpLinux宝库%Z X1f#wX&k4X/J-TU
# send the escape sequence to change the xterm titelbar:Linux宝库9HA vb&nM
echo -e "33]0;$107"Linux宝库)hOrIa2U
#
g N8O4X l qp0  在脚本中提供帮助是一种很好的编程习惯,这样方便其他用户(和您)使用和理解脚本。Linux宝库!I(^0^@}{Rga
命令行参数
h(k;u3~]0  我们已经见过$* 和 $1, $2 ... $9 等特殊变量,这些特殊变量包含了用户从命令行输入的参数。迄今为止,我们仅仅了解了一些简单的命令行语法(比如一些强制性的参数和查看帮助的-h选项)。但是在编写更复杂的程序时,您可能会发现您需要更多的自定义的选项。通常的惯例是在所有可选的参数之前加一个减号,后面再加上参数值 (比如文件名)。Linux宝库hZ"]c"~:E
  有好多方法可以实现对输入参数的分析,但是下面的使用case表达式的例子无遗是一个不错的方法。Linux宝库'@Al M#j#v9|1_\
#!/bin/sh
#M&^phS;\ z"w0help()
y!SA9~9~m'\0{Linux宝库Oxt-J$|dZ:e;w+x)j
 cat <
A@(n E:[0This is a generic command line parser demo.
~K EcnM P1r:nW0USAGE EXAMPLE: cmdparser -l hello -f -- -somefile1 somefile2
JAnT0z?{t0HELPLinux宝库 x6J1w]4e E:]3jj'lL
 exit 0Linux宝库g2`[ B!M"m)|#m&E
}Linux宝库Y&H_.A$vGg[6vB4j
while [ -n "$1" ]; doLinux宝库8y,Tp6cdr6OhP ]
case $1 in
7t R;m0S-C5Q#f^E0  -h) help;shift 1;; # function help is calledLinux宝库vm XC7lY*hym8b
  -f) opt_f=1;shift 1;; # variable opt_f is set
Q QH*Xj0  -l) opt_l=$2;shift 2;; # -l takes an argument -> shift by 2Linux宝库 CuGi.R_A
  --) shift;break;; # end of options
7zc Pq i6TW%m5O0  -*) echo "error: no such option $1. -h for help";exit 1;;Linux宝库)j gX_O Ou/e5V
  *) break;;
5Z| F.Y7sf*[]h0esac
C&KdO;^|!M0done
y B0g/lQr*C;f?0Linux宝库:hyK%L#r$M
echo "opt_f is $opt_f"Linux宝库kZE4Uu$F
echo "opt_l is $opt_l"
U&YZ*Ugm8z9B9Z,N0echo "first arg is $1"Linux宝库Z+GL#|p`
echo "2nd arg is $2"
/t;dVW.WA(_ b0  您可以这样运行该脚本:
R'q3\c ^g(i5F0cmdparser -l hello -f -- -somefile1 somefile2
R"F"qU,n{(e-W{0  返回的结果是:
fe IX1m|8El0opt_f is 1
{V(Ouc2g"a7Z0opt_l is hello
pO7g~#vT0first arg is -somefile1Linux宝库d0K&C ^)elhV|-D
2nd arg is somefile2
1yz5Va M6p2\d0  这个脚本是如何工作的呢?脚本首先在所有输入命令行参数中进行循环,将输入参数与case表达式进行比较,如果匹配则设置一个变量并且移除该参数。根据unix系统的惯例,首先输入的应该是包含减号的参数。
X3yA5D"F4y#W*| qd0实例Linux宝库&clqx0l*E
  一般编程步骤
MC$^1N} N;h^0  现在我们来讨论编写一个脚本的一般步骤。任何优秀的脚本都应该具有帮助和输入参数。并且写一个伪脚本(framework.sh),该脚本包含了大多数脚本都需要的框架结构,是一个非常不错的主意。这时候,在写一个新的脚本时我们只需要执行一下copy命令:
:r\V`$h%@Y0cp framework.sh myscriptLinux宝库X9`1o0}#q4a oA
 然后再插入自己的函数。
I&NP i8d:B \K0  让我们再看两个例子:Linux宝库,U[u6e!?I[qL7TI s
  二进制到十进制的转换
l AK'l5I0_6LE0  脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数。这也是一个用expr命令进行数学运算的例子:
ZF:Fg;e3V0#!/bin/sh
2?"w@u P h7bzs0# vim: set sw=4 ts=4 et:Linux宝库:E-O$HX#W a!za$m"|
help()
+M"Nh9t4Da!O0{
c&fn'k'r?0 cat <Linux宝库 J }"I-m8j?t
b2h -- convert binary to decimalLinux宝库(B6iIKy&vC
USAGE: b2h [-h] binarynumLinux宝库Y+jV3tcKnH
OPTIONS: -h help text
L5tCUG0EXAMPLE: b2h 111010
Pq-`3y{&j] b0will return 58Linux宝库)H:~;A(X$~8v z
HELPLinux宝库2Rs\e#C
 exit 0Linux宝库DQGEq
}
A(a9I+n Uq"f$W0error()
8?|_ ECs q*~0{
W#i6sB1o9z0  # print an error and exitLinux宝库:i U,Ut.f3L1\f
  echo "$1"Linux宝库 hq(F/C.Z
  exit 1Linux宝库:hH(}0Yuv$H
}Linux宝库#B2a,Jsb
lastchar()
k,__yI&u"f@+xh0{
T0E;sw+GZ4g0  # return the last character of a string in $rvalLinux宝库~i0n;PR)vT0|Jy.@
  if [ -z "$1" ]; thenLinux宝库N2b1{.l;t"}-WJ Lyu
    # empty string
4|F w5z6qd%d0    rval=""
jw Tz*Nfm0    return
oGam,t$h0m8]\0  fi
0C(Z4a*y'o5p-A Y0  # wc puts some space behind the output this is why we need sed:
E'b&Fb-V Mx0  numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `Linux宝库4uu S0B&QMOI{:l
  # now cut out the last char
n x^PMk l6@0  rval=`echo -n "$1" | cut -b $numofchar`
$b%hc:i:UV#uO#q0}
*z/VD9}*qd p0Linux宝库!k!q1|HH5}5G
chop()Linux宝库4dg&oCCv6o
{
b R[eS~;a0  # remove the last character in string and return it in $rvalLinux宝库@rna?H\BSxu7l
  if [ -z "$1" ]; thenLinux宝库1@aplL%A$K
    # empty string
\7j3BZ1GV0    rval=""
A$U IQ)J*u;`#F0    return
_^"g,[m)z}U0  fiLinux宝库tg~E-Y$O
  # wc puts some space behind the output this is why we need sed:Linux宝库a2`-m&{v b#U
  numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `Linux宝库P?$J#px;i0b
  if [ "$numofchar" = "1" ]; then
,Nq8F"L9tz*l._0    # only one char in stringLinux宝库 g|@#].`0c
    rval=""Linux宝库&A9Sth!IE6vw
    return
-op.A+_$P/vi0  fiLinux宝库d)bW/Z'a j vL
  numofcharminus1=`expr $numofchar "-" 1`
+M9gDE3i0  # now cut all but the last char:
0P2N`(ww,Sp'BM0  rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`
(l X5mDGQ(v0}Linux宝库Y3KES)sD
while [ -n "$1" ]; do
L*K)kf t&B j w!a`?IF0case $1 in
0E/K8T;D0w`+M0  -h) help;shift 1;; # function help is called
B `3W%t;y%A+b;[m0  --) shift;break;; # end of optionsLinux宝库.[t q#z Xl_G?&H@
  -*) error "error: no such option $1. -h for help";;
j IR Vu0  *) break;;Linux宝库"D(wd jL1n/E
esac
DY3y!S.@ _ DNh0doneLinux宝库?L e+Iklsk
# The main programLinux宝库 C([z;AS3Ue
sum=0Linux宝库V8^-N GX2p2U
weight=1Linux宝库5TK6hN bo&S T
# one arg must be given:
%P)Z5Y?Uz0[ -z "$1" ] && help
%g M*m@0\/q9I%M3A0binnum="$1"
+Jyl Z+q4u3iC0binnumorig="$1"
y UDx,e0
6h@RLe0while [ -n "$binnum" ]; doLinux宝库A5f3_ Gq7` ~
  lastchar "$binnum"
9D#tCBR/oOj XQ0  if [ "$rval" = "1" ]; then
Qz zMDwiro&Q4E5w0    sum=`expr "$weight" "+" "$sum"`Linux宝库&W @5Du-pgX tnyx
  fiLinux宝库D+l#vd]/xv5RU{K u
  # remove the last position in $binnum
(s%?{#r/P)Hj l0  chop "$binnum"
{@;g;f/S*S0  binnum="$rval"Linux宝库 tb~i&K8cW6x*~a
  weight=`expr "$weight" "*" 2`Linux宝库%NY r*q5Ai @{T Z"l7C
doneLinux宝库?C5O]O"O"|
echo "binary $binnumorig is decimal $sum"Linux宝库q-\u*f?
#Linux宝库']4L7m-K1AmO Nx
  该脚本使用的算法是利用十进制和二进制数权值 (1,2,4,8,16,..),比如二进制"10"可以这样转换成十进制:
(}-U#x |*XbS~.t00 * 1 + 1 * 2 = 2Linux宝库cR XR(k/v%VUaf
  为了得到单个的二进制数我们是用了lastchar 函数。该函数使用wc –c计算字符个数,然后使用cut命令取出末尾一个字符。Chop函数的功能则是移除最后一个字符。
~0l_a&Ng1{0  文件循环程序
'LisSI%Fl0  或许您是想将所有发出的邮件保存到一个文件中的人们中的一员,但是在过了几个月以后,这个文件可能会变得很大以至于使对该文件的访问速度变慢。下面的脚本rotatefile 可以解决这个问题。这个脚本可以重命名邮件保存文件(假设为outmail)为outmail.1,而对于outmail.1就变成了outmail.2 等等等等...
$A(J6B3]MA0#!/bin/shLinux宝库Sv:Y;QH
# vim: set sw=4 ts=4 et:Linux宝库AF9yZ!z
ver="0.1"Linux宝库6h_T W'G&Wv
help()Linux宝库4W0[M\*VS9d
{Linux宝库V;i BN5r:aUC
  cat <Linux宝库*o-`t.DDF
rotatefile -- rotate the file nameLinux宝库,n:YgQ `e'J

S9yo7O2O4A.`0USAGE: rotatefile [-h] filenameLinux宝库J9fZ-b"v9M7o

b:xWu*VU ] j0OPTIONS: -h help text
@mC#PK a%C0EXAMPLE: rotatefile outLinux宝库 Dejm8rE8D
This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1Linux宝库g5S7L'p)w
and create an empty out-fileLinux宝库z&K5|nim h
The max number is 10Linux宝库@Q^LtI\
version $verLinux宝库'cLl|W5g6D
HELPLinux宝库y#i5TVf'T!Yh)IQ$M
  exit 0Linux宝库JFa/l`_
}
u ?~C'zMD0Linux宝库c*Swj"z9Cmw,j
error()Linux宝库&i O0C?.ZHq
{
9twVW Sw0  echo "$1"
T5n,N-g\4c\0JF0  exit 1Linux宝库4[6^ i'ek,O!Z
}
+X U[ rGrm0while [ -n "$1" ]; doLinux宝库aw"c qG4py%Y
case $1 in
2V#sym}'|n[+c0  -h) help;shift 1;;
x)HI$U]Y7o0  --) break;;
j8dmrR0VB"S0  -*) echo "error: no such option $1. -h for help";exit 1;;Linux宝库gO}n's(]e&c
  *) break;;
-vy0et%gI0esacLinux宝库D0u#NwNN |&s
doneLinux宝库{!GV)|3qMY
# input check:
#W_,s!VU0if [ -z "$1" ] ; thenLinux宝库F O a.m%b{
error "ERROR: you must specify a file, use -h for help"
3BK[ZhMk?0fiLinux宝库@7JCB&zw%bh
filen="$1"
whM[VC"hC0# rename any .1 , .2 etc file:Linux宝库 W_PS!Hc3V%z
for n in 9 8 7 6 5 4 3 2 1; doLinux宝库Z*O{*ZQb
  if [ -f "$filen.$n" ]; thenLinux宝库 o'W5C|$A'M$I
    p=`expr $n + 1`Linux宝库F@ y4I6@EWjN3d
    echo "mv $filen.$n $filen.$p"
a ]q.h0ab0    mv $filen.$n $filen.$pLinux宝库b5Q5LpJ,|&XgjAU
  fiLinux宝库w;Y#L.B0c v^W
done
YsK#Oah[u,['tg0# rename the original file:
DJ~ a Ut0if [ -f "$filen" ]; thenLinux宝库 p;R/{ uv
  echo "mv $filen $filen.1"Linux宝库^p%t-\$Mx'm2L
  mv $filen $filen.1
wIx[kP(X0fi
.i,A oMW0echo touch $filenLinux宝库)?6kozx ]I R/H
touch $filen
%g3e(P8p9S(h5mi2R0  这个脚本是如何工作的呢?在检测用户提供了一个文件名以后,我们进行一个9到1的循环。文件9被命名为10,文件8重命名为9等等。循环完成之后,我们将原始文件命名为文件1同时建立一个与原始文件同名的空文件。
2Aq$I5LT|yA Q0调试
h8C En.G"qh#O]0  最简单的调试命令当然是使用echo命令。您可以使用echo在任何怀疑出错的地方打印任何变量值。这也是绝大多数的shell程序员要花费80%的时间来调试程序的原因。Shell程序的好处在于不需要重新编译,插入一个echo命令也不需要多少时间。Linux宝库9W4X8k eb`T
  shell也有一个真实的调试模式。如果在脚本"strangescript" 中有错误,您可以这样来进行调试:Linux宝库)~+|`#S2Q,k6l*S
sh -x strangescript
OBF4YY n O`$Z0  这将执行该脚本并显示所有变量的值。
/z~#W_9E#W0  shell还有一个不需要执行脚本只是检查语法的模式。可以这样使用:
Am%Vlh)So L4k0sh -n your_script
!?"l(Z [ [L_0  这将返回所有语法错误。
"]9Z3s;L"M[bv0  我们希望您现在可以开始写您自己的shell脚本,希望您玩得开心。
.U8q$DE[5WE;T0
Linux联盟收集整理

TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar