打印

不能不看,Unix下shell程序编写

我比较喜欢Shell
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP

不过掌握的不精
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP

Shell是什么?
  任何发明都具有供用户使用的界面。UNIX供用户使用的界面就是Shell(DOS的command熟悉吧,但UNIX的要强大的多)。 Shell为用户提供了输入命令和参数并可得到命令执行结果的环境。

  为了不同的需要,UNIX提供了不同的Shell。现在的UNIX大部分都支持BourneShell,以下教程就以BourneShell(Bsh)为例,一步步的领略UNIX Shell的强大功能,占先其强大魅力,达到更方便灵活的管理、应用UNIX的目的。

  1.UNIX内核和Shell的交互方法

  启动UNIX时,程序UNIX(内核)将被调入计算机内存,并一直保留在内存中直到机器关闭。在引导过程中,程序 init将进入后台运行一直到机器关闭。该程序查询文件/etc/inittab,该文件列出了连接终端的各个端口及其特征。当发现一个活动的终端时,init程序调用getty程序在终端上显示login等登陆信息。(username和passwd),在输入密码后, getty调用login进程,该进程根据文件/etc/passwd的内容来验证用户的身份。若用户通过身份验证,login进程 把用户的home目录设置成当前目录并把控制交给一系列setup程序。setup程序可以是指定的应用程序,通常setup程序 为一个Shell程序,如:/bin/sh 即Bourne Shell(command出来了,呵呵)。

   得到控制后,Shell程序读取并执行文件/etc/.profile以及.profile。这两个文件分别建立了系统范围内的和 该用户自己的工作环境。最后Shell显示命令提示符,如$。(这是以bsh为例,若是csh,为.cshrc,ksh为.kshrc,bash为.bashrc等等)    

  注不妨把/etc/.profile和.profile看成DOS的autoexec.bat 或 config.sys文件)

  当shell退出时,内核把控制交给init程序,该程序重新启动自动登陆过程。有两种方法使shell退出,一是用户执行exit命令,二是 内核(例如root用kill命令)发出一个kill命令结束shell进程。shell退出后,内核回收用户及程序使用的资源。

  用户登陆后,用户命令同计算机交互的关系为:命令进程--->Shell程序--->UNIX内核--->计算机硬件。当用户输入一个命令,如$ls, Shell将定位其可执行文件/bin/ls并把其传递给内核执行。内核产生一个新的子进程调用并执行/bin/ls。当程序执行完毕后,内核取消 该子进程并把控制交给其父进程,即Shell程序。例如执行:

    $ps

    该命令将会列出用户正在执行的进程,即Shell程序(下来详细说说,别急现在)和ps程序。若执行:

    $sleep 10 &
     $ps

  其中第一条命令将产生一个在后台执行的sleep子进程。ps命令执行时会显示出该子进程。

  每当用户执行一条命令时,就会产生一个子进程。该子进程的执行与其父进程或Shell完全无关,这样可以使Shell去做其他工作。(Shell只是把用户的意图告诉内核,然后该干嘛干嘛) 现在windows有个计划任务(在固定的时间,日期自动执行某任务),其实UNIX很早就有这个功能了,也就是所谓的Shell的自动执行。一些UNIX 资源,如cron可以自动执行Shell程序而无需用户的参与,(这个功能好象在/var/spool/crotab目录里)。 Crontab 程序对于系统管理员来说是非常有用的。Cron 服务用于计划程序在特定时间(月、日、周、时、分)运行。我们以root的crontab 为例。根用户的 crontab 文件放在 /var/spool/crontab/root 中,其格式如下:

  (1)  (2)  (3)  (4)  (5)  (6)
   0   0   *   *   3   /usr/bin/updatedb
       1. 分钟 (0-60)
       2. 小时 (0-23)
       3. 日 (1
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP

-31)
       4. 月 (1-12)
       5. 星期 (1-7)
       6. 所要运行的程序
   2.Shell的功能和特点
   1>命令行解释
   2>使用保留字
   3>使用Shell元字符(通配符)
   4>可处理程序命令
   5>使用输入输出重定向和管道
   6>维护一些变量
   7>运行环境控制
   8>支持Shell编程
  对于\"命令行解释\"就不多说了,就是在shell提示符(例如:\"$\",\"%\",\"#\"等)后输入一行unix命令,Shell将接收用户的输入。

  \"使用保留字\":Shell有一些具有特殊意义的字,例如在Shell脚本中,do,done,for等字用来控制循环操作,if,then等控制条件操作。 保留字随Shell环境的不同而不同。

  \"通配符\":* 匹配任何位置
        ? 匹配单个字符
        [] 匹配的字符范围或列表 例如:

          $ls [a-c]*

          将列出以a-c范围内字符开头的所有文件
          $ls [a,m,t]*
          将列出以e,m或t开头的所有文件

  \"程序命令\" :当用户输入命令后,Shell读取环境变量$path(一般在用户自己的.profile中设置),该变量包含了命令可执行文件可能存在的目录列表。 shell从这些目录中寻找命令所对应的可执行文件,然后将该文件送给内核执行。

  \"输入输出重定向及管道\" :重定向的功能同DOS的重定向功能:

     \">\" 重定向输出
     \"<\" 重定向输入

  而管道符号,是unix功能强大的一个地方,符号是一条竖线:\"|\",用法: command 1 | command 2 他的功能是把第一个命令command 1执行的结果作为command 2的输入传给command 2,例如:

    $ls -s|sort -nr|pg

  该命令列出当前目录中的所有文件,并把输出送给sort命令作为输入,sort命令按数字递减的顺序把ls的输出排序。然后把排序后的 内容传送给pg命令,pg命令在显示器上显示sort命令排序后的内容。

  \"维护变量\" :Shell可以维护一些变量。变量中存放一些数据供以后使用。用户可以用\"=\"给变量赋值,如:

         $lookup=/usr/mydir

该命令建立一个名为lookup的变量并给其赋值/usr/mydir,以后用户可以在命令行中使用lookup来代替/usr/mydir,例如:          
          $echo $lookup
          结果显示:/usr/mydir

         为了使变量能被子进程使用,可用exprot命令,例如:

          $lookup=/usr/mydir
          $export lookup

  \"运行环境控制\" :当用户登陆启动shell后,shell要为用户创建一个工作的环境,如下:

  1>当login程序激活用户shell后,将为用户建立环境变量。从/etc/profile和.profile文件中读出,在这些文件中一般都用$TERM 变量设置终端类型,用$PATH变量设置Shell寻找可执行文件的路径。

   2>从/etc/passwd文件或命令行启动shell时,用户可以给shell程序指定一些参数,例如\"-x\",可以在命令执行前显示该命令及其参数。后面详细介绍这些参数。

  \"shell编程\" :本文主要介绍的内容。

  shell本身也是一种语言(*可以先理解为unix命令的组合,加上类C的条件,循环等程序控制语句,类似dos批处理,但要强大的多),用户可以 通过shell编程(脚本,文本文件),完成特定的工作。

SHELL变量

  下面我们详细的介绍Bourne Shell的编程:

  自从贝尔实验室设计了Bourne Shell。从那时起许多厂商根据不同的硬件平台设计了许多版本
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP

得unix。但在众多版本的unix中,Bourne Shell 一直保持一致。
   1>Bsh的启动:用户在登陆后,系统根据文件/etc/passwd中有关该用户的信息项启动Shell。例如某用户在passwd中 的信息项为:
    ice_walk:!:411:103:Imsnow ,ice_walk:/home/ice_walk:/bin/bsh

  则表明,用户名是ice_walk等信息,在最后一项\"/bin/bsh\"表明用户的sh环境类型是bsh,于是系统启动之。在启动或执行(包括下面我们要讲 的shell程序--脚本)过程中可以使用以下一些参数,我们一一说明:

  -a 将所有变量输出
   -c \"string\"从string中读取命令
   -e 使用非交互式模式
   -f 禁止shell文件名产生
   -h 定义
   -i 交互式模式
   -k 为命令的执行设置选项
   -n 读取命令但不执行
   -r 受限模式
   -s 命令从标准输入读取
   -t 执行一命令,然后退出shell
   -u 在替换时,使用未设置的变量将会出错
   -v 显示shell的输入行
   -x 跟踪模式,显示执行的命令
许多模式可以组合起来用,您可以试试了,但-ei好象不行,你说why呢?

  使用set可以设置或取消shell的选项来改变shell环境。打开选项用\"-\",关闭选项用\"+\",多数unix允许打开或关闭a、f、e、h、k、n、 u、v和x选项。若显示Shell中已经设置的选项,执行:

    $echo $-

  Bsh中每个用户的home目录下都有一个.profile文件,可以修改该文件来修改shell环境。为了增加一个可执行文件的路径(例如/ice_walk/bin), 可以把下面代码加入.profile中

    PATH=$PATH:/ice_walk/bin;exprot PATH

   .profile中shell的环境变量意思如下:

    CDPATH 执行cd命令时使用的搜索路径
     HOME 用户的home目录
     IFS 内部的域分割符,一般为空格符、制表符、或换行符
     MAIL 指定特定文件(信箱)的路径,有UNIX邮件系统使用
     PATH 寻找命令的搜索路径(同dos的config.sys的 path)
     PS1 主命令提示符,默认是\"$\"
     PS2 从命令提示符,默认是\">\"
     TERM 使用终端类型

  2>Bsh里特殊字符及其含义

  在Bsh中有一组非字母字符。这些字符的用途分为四类:作为特殊变量名、产生文件名、数据或程序控制以及引用和逃逸字符控制。他们 可以让用户在Shell中使用最少的代码完成复杂的任务。

     *> Shell变量名使用的特殊字符
         $# 传送给命令Shell的参数序号
         $- 在Shell启动或使用set命令时提供选项
         $? 上一条命令执行后返回的值
         $$ 当前shell的进程号
         $! 上一个子进程的进程号
         $@ 所有的参数,每个都用双括号括起
         $* 所有参数,用双括号括起
         $n 位置参数值,n表示位置
         $0 当前shell名
      *>产生文件名的特殊字符
         包括\"*\",\"?\",\"[]\",上面讲过,不再多说。
      *>数据或程序控制使用的特殊字符
         >(file) 输出重定向到文件中(没有文件则创建,有则覆盖)
         >>(file) 输出重定向到文件中(没有则创建,有则追加到文件尾部)
         <(file) 输入重定向到文件
         ; 命令分割符
         | 管道符
         & 后台运行(例如:sleep 10 &
         ` ` 命令替换,重定向一
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP

条命令的输出作为另一命令的参数
      *>对于引用或逃逸的特殊字符
  Bsh用单引号\' \'和双引号\" \"将特殊字符或由空白分隔的字引用起来组成一个简单的数据串.使用单引号和双引号的区别是双引号中的内容可进行参数和变量替换.逃逸字符也一样.

        $echo \"$HOME $PATH\"
         结果显示$/u/ice_walk/bin:/etc:/usr/bin
         而$echo \'$HOME $PATH\' 结果显示$HOME $PATH

  shell的逃逸符是一个\"\\\",表示其后的字符不具有特殊的含义或不是shell的函数

        $echo \\$HOME $PATH
         结果显$$HOME /bin:/etc:/usr/bin:

3>Bsh的变量

  前面我们在多个地方引用了变量,当Shell遇到一个\"$\"符时(没有被引用或逃逸),它将认为其后为一变量。不论该变量是环境变量还是用户自定义的变量,在命令行中变量名要被变量值替换。例如命令:ls $HOME将列出变量HOME对应目录下的文件。 用户可以在命令行中的任何地方进行变量替换。包括命令名本身,例如:

    $dir=ls
     $$dir f*

  将列出以f开头的文件。

  现在详细的介绍下Bsh的变量。Bsh中有四类变量:用户定义的变量、位置变量(shell参数)、预定义变量及环境变量。

   用户定义的变量:

  用户定义的变量由字母和下划线组成,并且变量名的第一个字符不能为数字(0~9)。与其他UNIX名字一样,变量名是大小写敏感的。用户可以在命令行上用\"=\"给变量赋值,例如:

    $NAME=ice_walk

  给变量NAME赋值为ice_walk,在应用变量NAME的时候,在NAME前加\"$\"即可,前面已说,不再废话(别说我废话多,关键是没当过老师)。可以用变量和其他字符组成新的字,例如:

    $SUN=sun
     $echo ${SUN}day

  在应用shell变量时候,可以在变量名字两边$后面加上{},以更加清楚的显示给shell,哪个是真正的变量,以实现字符串的合并等功能。

   结果显示:sunday(注意不能echo $SUNday,因为SUNday变量没定义,读者试下执行结果) 用户也可以在命令行上同时对多个变量赋值,赋值语句之间用空格分开:

    $X=x Y=y

    注意变量赋值是从右到左进行的

    $X=$Y Y=y
     X的值是y
     $X=z Y=$Z

    Y的值是空(变量未赋值时,shell不报错,而是赋值为空)

  用户可以使用\"unset <变量>\"命令清除给变量赋的值
   用户使用变量时要在其前面加一\"$\"符,使变量名被变量值所替换。Bsh可以进行变量的条件替换,即只有某种条件发生时才进行替换。替换条件放在一对大括号{}中,如:

    ${variable: -value} variable是一变量值,value是变量替换使用的默认值

    $echo Hello $UNAME
     结果显示:Hello
     $echo Hello ${UNAME: -there}
     结果显示:Hello there
     $echo $UNAME
     结果显示: (空)
     $UNAME=John
     $echo Hello ${UNAME: -there}
     结果显示:Hello John

  可以看出,变量替换时将使用命令行中定义的默认值,但变量的值并没有因此而改变。另外一种替换的方法是不但使用默认值进行替换,而且将默认值赋给该变量。其形式如下:

    ${variable:=value}

  该形式在变量替换后同时把值value符给变量variable。

    $echo Hello $UNAME
     结果显示:Hello
     $echo Hello ${UNAME:=there}
     结
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP

果显示:Hello there
     $echo $UNAME
     结果显示:there
     $UNAME=John
     $echo Hello ${UNAME:-there}
     结果显示:Hello John
  变量替换的值也可以是` `括起来的命令:

    $USERDIR={$Mydir: -`pwd`}

  第三种变量的替换方法是只有当变量已赋值时才用指定值替换形式:

    ${variable: +value}

    只有变量variable已赋值时,其值才用value替换,否则不进行任何替换,例如:

    $ERROPT=A
     $echo ${ERROPT: +\"Error tracking is acitive\"}
     结果显示:Error tracking is acitive
     $ERROPT=
     $echo ${ERROPT: +\"Error tracking is acitive\"}
     结果显示: (空)

  我们还可以使用错误检查的条件进行变量替换:

    ${variable:?message}
当变量variable已设置时,正常替换。否则消息message将送到标准错误输出(若此替换出现在shell程序中,那么该程序将终止)。 例如:

    $UNAME=
     $echo $ {UNAME:?\"UNAME HAS NOT BEEN SET\"}
     结果显示:UNAME HAS NOT BEEN SET

    $UNAME=Stephanie
     $echo $ {UNAME:?\"UNAME HAS NOT BEEN SET\"}

    结果显示:Stephanie
     当没有指定message时,shell将显示一条默认的消息,例如:

    $UNAME=
     $echo $ {UNAME:?}
     结果显示:sh:UNAMEarameter null or not set

4>位置变量或Shell参数

  在shell解释用户的命令时,将把命令行的第一个字作为命令,而其他的字作为参数。当命令对应的可执行文件为Shell程序时,这些参数将作为位置变量传送给该程序。第一个参数记为$1,第二个为$2....第九个为$9。其中1到9是真正的参数名,\"$\"符只是用来标识变量的替换。

  位置变量$0指命令对应的可执行文件名。在后面将详细介绍位置变量。

  1.只读变量

  用户将变量赋值后,为了防止以后对该变量的修改,可以用以下命令将该变量设置为只读变量:

    readonly variable

  2.export命令

  shell执行一个程序时,首先为该程序建立一个新的执行环境,称为子shell。在Bourne Shell中变量都是局部的,即他们只在创建他们的Shell中有意义。用户可以用export命令让变量被其他子Shell识别。但某用户的变量是没法让其他用户使用的。

  当用户启动一个新shell时,该shell将使用默认的提示符。因为赋给变量PS1的值只在当前shell中有效。为了让子Shell使用当前Shell中定义的提示符号,可以使用export命令:

    $PS1=\"Enter command:\"
     Enter command:export PS1
     Enter command:sh
     Enter command:

    此时变量PS1变成了全局变量。它可以被其子Shell使用。当变量被设置成全局的以后,将一直保持有效直到用户退出该变量所在的Shell。用户可以在文件.profile中给一个变量永久赋值。详见\"规范Shell\"。

基本语句

  从本节起,我们将详细介绍Shell程序设计的基本知识,通过编写Shell脚本,用户可以根据自己的需要有条件的或者重复的执行命令。通过Shell程序,可以把单个的UNIX命令组合成一个完全实用的工具,完成用户的任务。

  1>什么是Shell程序

  
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP

当用户在UNIX Shell中输入了一条复杂的命令,如:
    $ls -R /|greo myname |pg

  我们可以称用户在对Shell编程,当把这条语句写在一个文件里,并且符给该文件可执行权限,那么该文件就是我们传统上说的Shell程序。

  2>简单的Shell程序

  假设用户每天使用下述命令备份自己的数据文件:

    $cd /usr/icewalk;ls * |cpio -o > /dev/fd0

  我们可以把它写在一个文件,如:ba.sh中:

    $cat >ba.sh
     cd /usr/icewalk
     ls * |cpio -o > /dev/fd0
     ^D  (ctrl_d)

  程序ba.sh就是Shell脚本,用户可以用vi或其他编辑工具编写更复杂的脚本。

  此时用户备份文件只需要执行Shell程序ba.sh,执行时需在当前Shell中创建一个子Shell:

    $sh ba.sh

  程序sh与用户登陆时执行的Bourne Shell相同,但当Sh命令带参数ba.sh后,它将不再是一个交互式的Shell,而是直接从文件ba.sh中读取命令。

  执行ba.sh中命令的另一方法是给文件ba.sh执行权限:

    $chmod +x ba.sh

  此时,用户可以输入文件名ba.sh做为一个命令来备份自己的数据,需要注意的是,用这种方法执行命令的时候,文件ba.sh必须存在于环境变量$PATH所指定的路径上。
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP

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

□Script的基本结构及观念

□Bourne Shell

一、变数

二、执行命令

三、流程控制

□C Shell

一、变数

二、执行命令

三、流程控制

□附录A expr命令

□附录B test命令

□前言

在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。

除了在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

结果如下:
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP

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 语法以及流程图如下 语法以及流程图如下

if(condition)

then

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 语法以及流程图如下

if(condition)

then

then-commands

else

else-commands

fi

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

if(condition1)

then

commands1

elif(condition2)

then

commands2

else

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\'
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢?

TOP


感谢一直以来您对我们的支持!
当前时区 GMT+8, 现在时间是 2008-9-7 20:28 京ICP证060528 号