找回密码
 注册
搜索
热搜: 回贴
  • 前程无忧官网首页 有什么好的平台可以
  • 最新的销售平台 互联网营销的平台有哪
  • 制作网页的基本流程 网页制作和网页设
  • 【帝国CMS】输出带序号的列表(数字排
  • 网站建设公司 三一,中联,极东泵车的
  • 织梦 建站 织梦网站模版后台怎么更改
  • 云服务官网 哪些网站有免费的简历模板
  • 如何建网站要什么条件 建网站要用什么
  • 吉林市移动公司电话 吉林省退休人员网
  • 设计类毕业论文 网站设计与实现毕业论
查看: 530|回复: 7

Shell编程

[复制链接]
发表于 2008-11-12 19:54:35 | 显示全部楼层 |阅读模式 IP:江苏南通
在DOS 中,你可能会从事一些例行的重覆性工作,此时你会将这些重覆性的命令写成批次档,只要执行这个批次档就等於执行这些命令。大家会问在UNIX中是否有批次处理这个东东,答案是有的。在UNIX中不只有如DOS 的批次处理,它的功能比起DOS 更强大,相对地也较复杂,已经和一般的高阶语言不相上下。在UNIX中大家都不叫做批次档,而叫做Shell Script。  



    一般而言,Shell Script的地位和其它的可执行档(或命令)是完全相同的,只不过Shell Script是以文字档的方式储存,而非二进位档。而执行Shell Script时,必须有一个程式将其内容转成一道道的命令执行,而这个程式其实就是Shell ,这也就是为什麽我们叫做Shell Script的原因(往後我们称为Script)。不同Shell 的Script基本上会有一些差异,所以我们不能将写给A shell 的Script用B shell 执行。而在UNIX中大家最常使用Bourne Shell以及C Shell ,所以这堂课就介绍这两种Script的写法。  



将文字档设为可执行的Shell Script  



    如果我们已经写好Script,如何将其设成可执行档呢?因为Script其实是一个可执行档,所以必须将其存取权设定成可执行。我们可以使用下列命令更改存取权:  

chmod u+x filename 只有自己可以执行,其它人不能执行  

chmod ug+x filename 只有自己以及同一群可以执行,其它人不能执行  

chmod +x filename 所有人都可以执行  



而我们如何指定使用那一个Shell 来解释所写的Script呢?几种基本的指定方式如下所述:  

1. 如果Script的第一个非空白字元不是"#",则它会使用Bourne Shell。  

2. 如果Script的第一个非空白字元是"#"时,但不以"#!"开头时,则它会使用C Shell。  

3. 如果Script以"#!"开头,则"#!"後面所写的就是所使用的Shell,而且要将整个路径名称指出来。  



这里建议使用第三种方式指定Shell ,以确保所执行的就是所要的。Bourne Shell的路径名称为/bin/sh ,而C Shell 则为/bin/csh。   



1. 使用Bourne Shell

┌——————————┐ ┌——————————┐

│echo enter filename │ │#!/bin/sh           │

└——————————┘ └——————————┘



2. 使用C Shell

┌——————————┐ ┌——————————┐

│# C Shell Script    │ │#!/bin/csh          │

└——————————┘ └——————————┘



3. 使用/etc/perl

┌——————————┐

│#! /etc/perl        │

└——————————┘



    除了在Script内指定所使用的Shell 外,你也可以在命令列中强制指定。比如你要用C Shell 执行某个Script,你可以下这个命令:  

csh filename  



此时的Script的存取权就不一定要为可执行档,其内部所指定的Shell 也会无效,详细的情形後面会讨论。  



□Script的基本结构及观念  



    Script是以行为单位,我们所写的Script会被分解成一行一行来执行。而每一行可以是命令、注解、或是流程控制指令等。如果某一行尚未完成,可以在行末加上"" ,这个时候下一行的内容就会接到这一行的後面,成为同一行,如下  



┌———————————┐

│echo The message is │

│too long so we have │

│to split it into     │

│several lines         │

└———————————┘



当Script中出现"#" 时,再它後面的同一行文字即为注解,Shell 不会对其翻译。  



在Script中要执行一个命令的方法和在命令列中一样,你可以前景或背景执行,执行命令时也会需要设定一些环境变量。  



Script的流程控制和一般高阶语言的流程控制没有什麽两样,也和高阶语言一样有副程式。这些使得Script的功能更加强大。  



为了达到与高阶语言相同的效果,我们也可以在Script中设定变量,如此使Script 成为一个名付其实的高阶语言。  



□Bourne Shell  



一、变量  



Bourne Shell的变量型态只有字串变量,所以要使用数值运算则必须靠外部命令达 成目的。而其变量种类有下列几种:  



1. 使用者变量  



这是最常使用的变量,我们可以任何不包含空白字元的字串来当做变量名称。 设定变量值时则用下列方式:  

var=string  



取用变量时则在变量名称前加上一"$" 号。   



┌———————┐

│name=Tom      │

│echo name     │

│echo $name    │

└———————┘

结果如下:

name

Tom



2. 系统变量(环境变量)  



和使用者变量相似,只不过此种变量会将其值传给其所执行的命令。要将一使 用者变量设定为系统变量,只要加上:  

export var  



┌———————┐

│name=Tom      │

│export name   │

└———————┘



以下是使用者一进入系统之後就已设定好的系统变量:  

$HOME 使用者自己的目录  

$PATH 执行命令时所搜寻的目录  

$TZ 时区  

$MAILCHECK 每隔多少秒检查是否有新的信件  

$PS1 在命令列时的提示号  

$PS2 当命令尚未打完时,Shell 要求再输入时的提示号  

$MANPATH man 指令的搜寻路径  



3. 唯读的使用者变量  



和使用者变量相似,只不过这些变量不能被改变。要将使用者变量设成唯读的 ,只要加上:  

readonly var  



而若只打readonly则会列出所有唯读的变量。还有一点,系统变量不可以设定 成唯读的。  



┌———————┐

│name=Tom      │

│readonly name │

│echo $name    │

│name=John     │

│readonly      │

└———————┘



结果如下:

Tom

name: is read only

readonly name

readonly ......



4. 特殊变量  

    有些变量是一开始执行Script时就会设定,并且不以加以修改,但我们不叫它 唯读的系统变量,而叫它特殊变量(有些书会叫它唯读的系统变量),因为这 些变量是一执行程式时就有了,况且使用者无法将一般的系统变量设定成唯读 的。以下是一些等殊变量:  


$0 这个程式的执行名字  

$n 这个程式的第n个参数值,n=1..9  

$* 这个程式的所有参数  

$# 这个程式的参数个数  

$$ 这个程式的PID  

$! 执行上一个背景指令的PID  

$? 执行上一个指令的返回值  



    当你执行这个程式时的参数数目超过9 个时,我们可以使用shift 命令将参数 往前移一格,如此即可使用第10个以後的参数。除此之外,吾人可以用set 命 令改变$n及$*,方法如下:  

set string  



如此$*的值即为string,而分解後则会放入$n。如果set 命令後面没有参数, 则会列出所有已经设定的变量以及其值。  



档名:ex1 参数:this is a test  



┌———————————┐

│echo Filename: $0     │

│echo Arguments: $*    │

│echo No. of args.: $# │

│echo 2nd arg.: $2     │

│shift                 │

│echo No. of args.: $# │

│echo 2nd arg.: $2     │

│set hello, everyone   │

│echo Arguments: $*    │

│echo 2nd arg.: $2     │

└———————————┘

结果如下:

Filename: ex1

Arguments: this is a test

No. of args.: 4

2nd arg.: is

No. of args.: 3

2nd arg.: a

Arguments: hello, everyone

2nd arg.: everyone



值得一提的是,当你想从键盘输入一变量值时,你可以使用下面的命令:  

read var1 var2.....  



    这时read会将一个字分给一个变量。如果输入的字比变量还多,最後一个变量会将剩下的字当成其值。如果输入的字比变量还少,则後面的变量会设成空字串。 如果需要处理数值运算,我们可以使用expr命令。其参数及输出列於附录A。  



二、执行命令  



在Bourne Shell中有五种方法执行一个命令,而这五种方式所产生的果有些许的不 同。  



1. 直接下命令  

这个方式和在命令列中直接下命令的效果一样。  



2. 使用sh命令  

sh command  

这个档案必须是Bourne Shell的Script,但这个档案并不一定要设成可执行。 除此之外和直接下命令的方式一样。  



3. 使用"."命令  

. command   

这时和使用sh命令相似,只不过它不像sh一般会产生新的process ,相反地, 它会在原有的process 下完成工作。  



4. 使用exec命令  

exec command  

此时这个Script将会被所执行的命令所取代。当这个命令执行完毕之後,这个 Script也会随之结束。  



5. 使用命令替换  

    这是一个相当有用的方法。如果想要使某个命令的输出成为另一个命令的参数 时,就一定要使用这个方法。我们将命令列於两个"`" 号之间,而Shell 会以 这个命令执行後的输出结果代替这个命令以及两个"`" 符号。  



str='Current directory is '`pwd`  

echo $str  

结果如下:  

Current directory is /users/cc/mgtsai  

    这个意思是pwd 这个命令输出"/users/cc/mgtsai",而後整个字串代替原 来的`pwd` 设定str 变量,所以str 变量的内容则会有pwd 命令的输出。  



number=`expr $number + 1`  

    这就是先前所提要作数值运算的方法,基本上expr命令只将运算式解,而 後输出到标准输出上。如果要将某变量设定成其值,非得靠命令替换的方 式不可。这个例子是将number变量的值加1 後再存回number变量。  



三、流程控制  



    在介绍流程控制之前,我们先来看看test命令。test命令的参数是条件判断式,当 条件为真时则传回非零值,而条件为伪时则传回零。在所有的流程控制都必须用到 test命令来判断真伪。而test命令的使用方法则列於附录B。  



test $# = 0  



如果执行这个程式没有参数时,会传回非零值代表"$# = 0"这个条件成立。反 之则会传回零。  



以下介绍各种流程控制:  



1. if then语法以及流程图如下  



│ FALSE

if (condition) <condition>—┐

then │TRUE │

then-commands then-commands │

fi ├————┘  



condition 是一个test命令。往後所介绍的各种流程中的condition 都是test 命令。  

档名:chkarg  



┌———————————┐

│if (test $# != 0)     │

│ then                 │

│ echo Arg1: $1        │

│fi                    │

└———————————┘

$ chkarg Hello

Arg1: Hello

$ chkarg

$



2. if then else语法以及流程图如下  



│ FALSE

if (condition) <condition>—————┐

then │TRUE │

then-commands then-commands else-commands

else ├————————┘

else-commands │

fi



3. if then elif语法以及流程图如下  



│ FALSE

if (condition1) <condition1>—┐

then │TRUE │ FALSE

commands1 commands1 <condition2>—┐

elif (condition2) │ │ TRUE │

then │ commands2 commands3

commands2 ├—————┴————┘

else │

commands3



commands3

fi



echo 'word 1: c'

read word1

echo 'word 2: c'

read word2

echo 'word 3: c'

read word3

if (test "$word1" = "$word2" -a "$word2" = "$word3")

then

echo 'Match: words 1, 2, & 3'

elif (test "$word1" = "$word2")

then

echo 'Match: words 1 & 2'

elif (test "$word1" = "$word3")

then

echo 'Match: words 1 & 3'

elif (test "$word2" = "$word3")

then

echo 'Match: words 2 & 3'

else

echo 'No match'

fi



4. for in语法以及流程图如下  



│ FALSE

for var in arg-list ┌—<arg-list还有东西吗?>—┐

do │ │TRUE │

commands │ 从arg-list取得一项 │

done │ 放到变量var │

│ │ │

│ commands │

└——————┘ │

┌———————————┐ ┌—————┘

│for a in xx yy zz     │ │

│ do                   │

│ echo $a              │

│done                  │

└———————————┘

结果如下:

xx

yy



yy

zz



5. for语法以及流程图如下  



│ FALSE

for var ┌—<参数中还有东西吗?>—┐

do │ │TRUE │

commands │ 从参数中取得一项 │

done │ 放到变量var │

│ │ │

│ commands │

└—————┘ │

档名:lstarg ┌—————┘

┌———————————┐ │

│for a                 │

│ do                   │

│ echo $a              │

│done                  │

└———————————┘

$lstarg xx yy zz

xx

yy



yy

zz



6. while 语法以及流程图如下



│ FALSE

while (condition) ┌—<condition>—┐

do │ │TRUE │

commands │ commands │

done └————┘ │

┌————┘





┌———————————————┐

│number=0                      │

│while (test $number -lt 10)   │

│ do                           │

│ echo "$numberc"             │

│ number=`expr $number + 1`    │

│done                          │

│echo                          │

└———————————————┘

结果如下:

0123456789



7. until语法以及流程图如下   



│ TRUE

until (condition) ┌—<condition>—┐

do │ │FALSE │

commands │ commands │

done └————┘ │

┌————┘





它和while 的不同只在於while 是在条件为真时执行回圈,而until 是在条件 为假时执行回圈。  



8. break及continue  

这两者是用於for, while, until 等回圈控制下。break 会跳至done後方执行 ,而continue会跳至done执行,继续执行回圈。  



9. case语法以及流程图如下  



│ TRUE

case str in <str=pat1>————commands1—┐

pat1) commands1;; │FALSE TRUE │

pat2) commands2;; <str=pat2>————commands2—┤

pat3) commands3;; │FALSE TRUE │

esac <str=pat3>————commands3—┤

│FALSE │

├————————————┘





而pat 除了可以指定一些确定的字串,也可以指定字串的集合,如下  

* 任意字串  

? 任意字元  

[abc] a, b, 或c三字元其中之一  

[a-n] 从a到n的任一字元  

| 多重选择  



┌———————————————┐

│echo 'Enter A, B, or C: c'   │

│read letter                   │

│case $letter in               │

│ A|a) echo 'You entered A.';; │

│ B|b) echo 'You entered B.';; │

│ C|c) echo 'You entered C.';; │

│ *) echo 'Not A, B, or C';;   │

│esac                          │

└———————————————┘  



□附录A expr命令



命令格式



expr expression



叙述



expression是由字串以及运算子所组成,每个字串或是运算子之间必须用空白隔开 。下表是运算子的种类及功能,而优先顺序则以先後次序排列,我们可以利用小括 号来改变运算的优先次序。其运算结果则输出至标准输出上。



: 字串比较。比较的方式是以两字串的第一个字母开始,而以第二个字串的 字母结束。如果相同时,则输出第二个字串的字母个数,如果不同时则传 回0 。



* 乘法



/ 除法



% 取馀数



+ 加法



- 减法



< 小於



<= 小於等於



= 等於



!= 不等於



>= 大於等於



> 大於



& AND运算



| OR运算



当expression中含有"*", "(", ")" 等符号时,必须在其前面加上"" ,以免被 Shell 解释成其它意义。   



expr 2 * ( 3 + 4 ) 其输出为14



□附录B test命令



命令格式



test expression



叙述



expression中包含一个以上的判断准则以作为test评诂的标准。两准则间用"-a"代 表逻辑AND 运算,"-o"代表逻辑OR运算,而在准则前放置一"!" 代表NOT 运算。如 果没有括号,则优先权则为"!" > "-a" > "-o" 。和expr命令相同,相使用左右括 号时,必须在其前面加上"" 。以下是有关准则的叙述(合叙述时传回真,否则传 回伪):



string string不为空白字串



-n string string的长度大於0



-z string string的长度等於0



string1=string2 string1等於string2



string1!=string2 string1不等於string2



int1 -gt int2 int1大於int2



int1 -ge int2 int1大於等於int2



int1 -eq int2 int1等於int2



int1 -ne int2 int1不等於int2



int1 -le int2 int1小於等於int2



int1 -lt int2 int1小於int2



-e filename 如果文件存在则为真



-r filename 档案可读取



-w filename 档案可写入



-x filename 档案可执行



-f filename 档案为一般档



-d filename 档案为目录



-s filename 档案为非空的一般档



-c filename 如果文件存在且为字符型特殊文件则为真



-b filename 如果文件存在且为块特殊文件则为真



test -r "$filename" -a -s "$filename"
发表于 2009-11-16 08:05:04 | 显示全部楼层 IP:广东深圳
哈哈,有意思~顶顶 ,继续顶顶。继续顶哦
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-29 13:19 , Processed in 0.246573 second(s), 15 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表