【GNU/Linux实战手记之Emacs篇 中--Bash 编程】 作者:叶魏彬 MSN:fritz_yea@hotmail.com Copyright(C)Free Software Library,Org(http://yea.xiloo.com) 本文依照GNU Free Document Lience发布,任何人都可以将本文原封不动的复制、转载,但请务必保留此声明。作者不对本文所导致的任何结果负责。
七、Bash语法 在看过上一次的那个简单的shell程序之后,我们来深入研究一下shell强大的程序设计能力。Shell是一种很容易学习的程序设计语言,至少因为它能够在把各个小程序组合成一个大程序之前很容易的对它们分别进行交互式的测试。利用现代Unix操作系统的shell,我们可以编写出相当庞大的结构化程序。在接下来的几小节里,我们将学习: ·变量:字符串、数字、环境和参数 ·条件:shell中的布尔值 ·程序控制:if、elif、for、while、until、case ·函数 ·注释
为了确保Bash编程的严谨性和趣味性,我直接引用了WROX出版社的《Linux程序设计》一书第二章的部分内容和例程源代码。我想以学习的名义,我这里的引用应该不算盗版,至少它的源代码是基于GPL的。
1、变量 在shell里,使用变量之前并不需要事先对他们做出声明。我们可以在任何需要的时候直接创建并使用变量。默认情况下,变量类型为字符串,即使它所保存的是数值。Shell和其他的一些工具会自动识别“数值”型字符串,并按正确的方法对其进行操作。变量名区分大小写,这与Unix系统保持一致。因此变量var和Var以及VAR分别指不同的变量。变量命名原则与Unix文件命名原则相同,但是不允许有空格,更不能和现有系统命令重名。 在shell里,变量名前面加一个“$”字符,就可以获得它的内容。只要用到变量,我们就必须在它前面加上“$”,除非是对它进行赋值。赋值变量可以直接使用“=”,也可以使用read命令,将用户的输入赋给变量。请看下面的例子: $string=Hello $echo $string Hello $string="Guten Tag" $echo $string Guten Tag $string=1+2+3 $echo $string 1+2+3 $read string I love you /*用户输入,回车结束*/ $echo $string I love you /*读取变量内容*/
*注意,如果字符串里包含空格,就必须用引号把它们括起来。还要注意的是等号两边不能有空格。 **我说过,数字也被保存为字符串,因此“string=1+2+3”的结果仍是“1+2+3”,而不是“6”。 ***read读取用户输入的字符串,以回车结束。 1.1、引号的用法 一般情况下,参数之间是用空白字符分隔的,比如一个空格、一个制表符或一个换行符,如果想在一个一个参数里面包含一个或多个这样的空白字符,就必须给参数加上引号。 引号也有不同。如果你在双引号里包含变量,则会引起“名-值替换”,而在单引号里就不会。我们还可以在“$”号前加上“\”来取消它的特殊含义。 让我们来看看引号在变量输出中的作用: #!/bin/sh
myvar="Hi there"
echo $myvar echo "$myvar" echo ''''$myvar'''' echo \$myvar
echo Enter some text read myvar
echo ''''$myvar'''' now equals $myvar
exit 0
输出结果是:
Hi there Hi there $myvar $myvar Enter some text Hello world $myvar now equals Hello world
1.2、环境变量 脚本在执行的时候,某些变量会根据系统环境设定而进行初始化。这些环境变量通常使用大写,以便和用户自定义的变量区分,后者通常使用小写。下面是一些常用到的环境变量:
环境变量 说明 $HOME 当前用户的登录子目录 $PATH 以冒号分隔的用来分隔搜索命令的子目录清单 $PS1 命令行提示符,通常是“$”字符 $PS2 辅助提示符,用来提示后续输入,通常是“>”字符 $IFS 输入区的分隔符。当shell读取输入数据的时候会把一组字符看做是单词之间的分隔字符,它们通常是空格、制表符和换行符 $0 shell脚本程序的名字 $# 传递到脚本程序的参数个数 $$ 该shell脚本程序的进程ID,脚本程序一般会使用它来创建独一无二的临时文件,比如/tmp/tmpfile_$$
1.3、参数变量 如果你的脚本程序在调用的时候还带有参数,就会产生额外的一些变量。即使你什么参数也没传,上面的“$#”依然存在,只不过值是0罢了。
参数变量 说明 $1,$2... 脚本程序的参数 $* 一个全体参数组成的清单,这是一个单独的变量,各个参数之间用环境变量IFS中的第一个字符分隔开 $@ “$*”的一种变量,它不使用IFS环境变量
下面是使用环境变量和参数变量的一个例子:
#!/bin/sh salutation="Hello" echo $salutation echo "The program $0 is now running" echo "The second parameter was $2" echo "The first parameter was $1" echo "The parameter list was $*" echo "The user''''s home directory is $HOME"
echo "Please enter a new greeting" read salutation
echo $salutation echo "The script is now complete"
exit 0
输出结果是:
Hello The program ./try_var is now running The second parameter was The first parameter was The parameter list was The user''''s home directory is /home/yea Please enter a new greeting Sire Sire The script is now complete
2、条件测试 在实际工作中,大多数脚本程序都会大量使用“[ ]”或“test”命令——即shell的布尔判断命令。注意,“[ ]”和要被检查的条件之间留出空格。因为“[”与“test”实际上是一样的,而“test”命令后面要空格,所以“[”后面自然也得有空格了。有关“test”命令的使用,请参考“test”的手册页。我不在此赘述了。
3、控制结构——if、elif、for、while、until、case shell有一系列控制结构,而且它们同样与其他程序设计语言很相似。就某些结构而言(比如case语句),shell提供了更强大的功能。 为了减小篇幅,并且让大家看起来一目了然,我直接列出各控制结构的语法结构和例程,好在这样写并不会增加理解的难度。 3.1、if语句
if condition then statements else statements fi
if语句的例子
#!/bin/sh
echo "Is it morning? Please answer yes or no" read timeofday
if [ "$timeofday" = "yes" ]; then echo "Good morning" else echo "Good afternoon" fi
exit 0
3.2、elif语句
if condition then statements elif condition then statements else statements fi
elif语句的例子
#!/bin/sh
echo "Is it morning? Please answer yes or no" read timeofday
if [ $timeofday = "yes" ] then echo "Good morning" elif [ $timeofday = "no" ]; then echo "Good afternoon" else echo "Sorry, $timeofday not recognized. Enter yes or no" exit 1 fi
exit 0
3.3、for语句
for variable in values do statements done
for语句的例子
#!/bin/sh
for foo in bar fud 43 do echo $foo done
exit 0
3.4、while语句 假若我们要循环100次,用for的话就得从1一直写到100,这样太累了。它确实没有BASIC里的for方便——FOR I=1 TO 100 STEP 1,但是它有它的优势,这里暂且不谈。 对于上面的情况,我们可以使用while结构和数值替换结合在一起。while的语法结构是 while condition do statements done
看下面的例子 #!/bin/sh
foo=1 while [ "$foo" -le 20 ] do echo "Here we go again" foo=$(($foo+1)) done
exit 0
这里展示了$(command)结构的用法。
3.5、until语句 until和while很类似,只是把条件测试倒过来了。换句话说,就是循环将反复执行直到条件为真是停止,而不是当条件为真时执行。 until的语法为 until condition do statements done
until语句的例子 #!/bin/sh
until who | grep "$1" > /dev/null do sleep 60 done
# Now ring the bell and announce the unexpected user.
echo -e \\a echo "***** $1 has just logged in *****"
exit 0
3.6、case语句 case结构比我们前面见过的其他语句都稍微复杂些。它的语法如下所示: case variable in patten [| patten] ...) statements;; patten [| patten] ...) statements;; ... esac
其实这种语法结构要比我们一般所见到的case结构简洁(比如C/C++的switch~case结构),它可以将多个选项写在一起(就是[]中的可选部分)。需要注意的是,语句结尾要用两个分号“;;”,而不是一个分号。在statements里即可以是一条语句,又可以是数条语句。下面是数条语句的例子: #!/bin/sh
echo "Is it morning? Please answer yes or no" read timeofday
case "$timeofday" in yes | y | Yes | YES ) echo "Good Morning" echo "Up bright and early this morning?" ;; [nN]* ) echo "Good Afternoon" ;; * ) echo "Sorry, answer not recognised" echo "Please answer yes or no" exit 1 ;; esac
exit 0
4、函数 shell允许用户定义函数,以包含某些系统命令,形成执行模块。在shell里定义函数很简单,写出它的名字,加上一对空的“()”,在把有关的语句包含在一对花括号“{}”里,如下所示: function_name(){ statements } shell脚本的执行顺序是自顶向下,因此所有的函数声明都要出现在他执行之前,否则shell将找不到函数。
5、注释 shell脚本用“#”符号注释它之后的语句,直至行尾。这有点像C++里的“//”注释符。但是所有的脚本程序,第一行都由“#!”开头,并指定执行此脚本的程序。这里是“#”另一种功能。仅此而已。
八、实例——Mini Music Jukebox 使用上面的基本元素,我们就可以构件Bash脚本了。理论上,Bash脚本同样可以写出大型、复杂的程序。但是,这样肯定不如用C/C++、Java等编译型语言写的执行效率高。我们学习Bash编程的目的也是为了通过构造shell脚本来减小系统管理的负担,提高管理员的工作效率。所以我们的目标不是大型的程序,而是短小精干的小应用。我用Bash写下了下面的东西,用来播放我的音乐库。 #!/bin/bash # This is very simple Bash script.It just help us enjoy music. # Copyright (C) 2003, Free Software Library
# filename: play_music # To run this script, simply type follow command. # chmod +x play_music # ./play_music
# This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version.
# This program is distributed in the hopes that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details.
# You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc. # 67 [1] [2] 下一页 [C语言系列]C# 和 Linux 时间戳转换 [Web开发]PHP flock文件锁介绍 [Web开发]flock() Linux下的文件锁 [电脑应用]Linux下的六个免费的虚拟主机管理系统介绍 [电脑应用]Linux数据库大比拚 [操作系统]在Windows中玩转Linux操作系统 [办公软件]在RedHat Linux 9里安装gaim0.80 [办公软件]掌握 Linux 调试技术 [办公软件]理解 Linux 配置文件 [聊天工具]Real10 & Xpdf installation on Linux Box
|