分享
 
 
 

GNU/Linux实战手记之Emacs篇 中--Bash程序设计

王朝system·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

【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.

# 675 Mass Ave, Cambridge, MA 02139, USA.

# The first thing to do is to ensure that some global variables that we'll be using

# throughout the script are set up. We set the title and track files and a temporary file.

# We also trap Ctrl-C, so our temporary file is removed if the user interrupts the script.

# First,define some globle variables.

choice=""

menu_choice=""

quit=n

# Second,define some functions.

add_mp3(){

echo "Add MP3 files from $HOME/music/mp3 to playlist file \"mp3list\"."

find $HOME/music/mp3/ -iname *.mp3 >> $HOME/music/mp3list

}

add_ogg(){

echo "Add Ogg files from $HOME/music/ogg to playlist file \"ogglist\"."

find $HOME/music/ogg/ -iname *.ogg >> $HOME/music/ogglist

}

play_mp3(){

clear

echo "Playing MP3 files with mpg123."

echo "Control key:"

echo "s=>Stop, p=>Pause, f=>Forward, b=>Backward, q=Quit(Directly)"

echo "Also"

echo "Press Ctrl-C for next song, and press Ctrl-C twice within a short while to quit."

mpg123 -C --list $HOME/music/mp3list

return

}

play_ogg(){

clear

echo "Playing Ogg files with ogg123."

echo "Control key:"

echo "Press Ctrl-C for next song, and press Ctrl-C twice within a short while to quit."

echo

ogg123 $HOME/music/ogg # As the ogg123 do not support playlist, we never use the ogglist file.

return

}

welcome_msg(){

clear

echo

echo "Mini Music Jukwbox--A very simple program written in Bash script."

echo

echo "Before using it, you should at least have the following two program on your system:"

echo "ogg123 - needed for playing Ogg files."

echo "mpg123 - needed for playing MP3 files."

echo

echo "Do you have these software?(y/n):"

read choice

}

set_menu(){

clear

echo "Mini Music Jukwbox."

echo

echo "Options :"

echo

echo " 1) Add MP3 files to playlist"

echo " 2) Add Ogg files to playlist"

echo " 3) Play MP3"

echo " 4) Play Ogg"

echo " q) Quit"

echo

echo "Please enter your choice and then press return"

read menu_choice

}

# Final,the application proper

welcome_msg

if [ "$choice" = "y" ]

then

while [ "$quit" != "y" ]

do

set_menu

case "$menu_choice" in

1) add_mp3;;

2) add_ogg;;

3) play_mp3;;

4) play_ogg;;

q|Q) quit=y;;

*) echo "Sorry, choice not recognized";;

esac

done

else

exit 0

fi

echo "Thanks for using. Bye! :)"

exit 0

在shell模式下运行这个脚本。我在这里只使用了Bash的部分特性,你可以自行修改上面的程序,作为学习Bash的实验。

【GNU/Linux实战手记之Emacs篇 中】到此就结束了。这一篇仅涉及Bash,并未涉及Emacs,所以你完全可以将本篇看做是介绍Bash编程的独立的文章。但是由于我们一直是在Emacs这个环境下编写和调试脚本的,所以我仍将他归到Emacs篇中。在下一篇【GNU/Linux实战手记之Emacs篇 下】中我将介绍如何定制Emacs的IDE环境,使它更好用。我们下篇再见。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有