li
  当前位置:主页 > 操作系统 > 文章内容
li
Unix shell教程:Unix系列shell程序编写(下)
来源: www.ixdba.net  作者: IXDBA.NET官方    时间:2007-12-26   阅读:26  
本文章共7352字,分2页,当前第1页,快速翻页:
 

下接 Unix系列shell程序编写()

Until语句

  While语句中,只要某条件为真,则重复执行循环代码,until语句正好同while相反,该语句使循环代码重复执行,直到遇到某一条件为真才停止。

Until
语句的结构如下:
until command
  do
IXDBA.NET技术社区
    command
    command
    … …
  done

  可以用until语句替换上面备份程序的while语句,完成同样的功能:

until [ $ANS != Y -a $ANS != y ]

for
循环
  在介绍for循环之前,我们要学个非常有用的unix命令:shift。我们知道,对于位置变量或命令行参数,其个数必须是确定的,或者当Shell程序不知道其个数时,可以把所有参数一起赋值给变量$*。若用户要求Shell在不知道位置变量个数的情况下,还能逐个的把参数一一处理,也就是在$1后为$2,$2后面为$3等。在
shift
命令执行前变量$1的值在shift命令执行后就不可用了。

示例如下:

#
测试shift命令(x_shift.sh)
until [ $# -eq 0 ]
do
echo "
第一个参数为: $1 参数个数为: $#"
shift
done
执行以上程序x_shift.sh
$./x_shift.sh 1 2 3 4

结果显示如下:

第一个参数为: 1 参数个数为: 3
第一个参数为: 2 参数个数为: 2
第一个参数为: 3 参数个数为: 1
第一个参数为: 4 参数个数为: 0

从上可知shift命令每执行一次,变量的个数($#)减一,而变量值提前一位,下面代码用untilshift命令计算所有命令行参数的和。

#shift
上档命令的应用(x_shift2.sh)
if [ $# -eq 0 ]
then
echo "Usage:x_shift2.sh
参数"
exit 1
fi
sum=0
until [ $# -eq 0 ]
do
sum=`expr $sum + $1`
shift
done
echo "sum is: $sum"

执行上述程序:

$x_shift2.sh 10 20 15

其显示结果为:

45

  shift命令还有另外一个重要用途,Bsh定义了9个位置变量,从$1$9,这并不意味着用户在命令行只能使用9个参数,借助shift命令可以访问多于9个的参数。

  Shift命令一次移动参数的个数由其所带的参数指定。例如当shell程序处理完前九个命令行参数后,可以使用shift
9
命令把$10移到$1

  在熟悉了shift命令后,我们一起看看,Bsh程序中非常有用的for循环语句,这种循环同上面说的whileuntil循环不同,for语句中的循环是否执行并不由某个条件的真和假来决定,决定for循环是否继续的条件是参数表中是否还有未处理的参数。

For
语句的结构如下:

for variable in arg1 arg2 … argn
do
command
command
… …
done

下面是for循环的简单例子:

for LETTER in a b c d
do
echo $LETTER
done

程序执行结果如下:

a
b
c
d

在上面计算参数和的例子中,我们可以用for循环,实现如下:

#
测试 for 程序(x_for.sh)

if [ $# -eq 0 ]
then
   echo "Usage:x_for.sh 参数… …"
   exit 1
fi
sum=0
for I in $*
do
   sum=`expr $sum + $I`
done
echo "sum is: $sum"

中断循环指令

  在程序循环语句中,我们有时候希望遇到某中情况时候结束本次循环执行下次循环或结束这个循环,这就涉及到两条语句:continuebreakcontinue命令可使程序忽略其后循环体中的其他指令,直接进行下次循环,而break命令则立刻结束循环,执行循环体后面的的语句。

#
测试continue
I=1
while [ $I -lt 10 ]
do
  if [ $I -eq 3 ]
  then
    continue
  fi
  if [ $I -eq 7 ]
  then
    break
  fi
  echo "$I\c"
done

执行上面程序,结果如下:

12456789

与或结构

使用与/或结构有条件的执行命令

  Shell程序中可以使用多种不同的方法完成相同的功能,例如untilwhile语句就可以完成相同的功能,同样,除了if-then-else结构可以使命令有条件的执行外,$$||操作符也能完成上述功能。在C语言中这两个操作符分别表示逻辑与和逻辑或操作。在Bourne
Shell
中,用&&连接两条命令的含义只有前面一条命令成功执行了,后面的命令才会执行。

  &&操作的形式为:

    command && command

  例如语句:

    rm $TEMPDIR/* && echo "Files successfully removed"

  只有rm命令成功执行以后,才会执行echo命令。若用if-then语句实现上述功能,形式为:

    if rm $TEMPDIR/*
    then
      echo "Files successfully removed"
    fi
  相反,用||连接两条命令的含义为只有第一条命令执行失败才执行第二条命令,例如:

    rm $TEMPDIR/* || echo "File were not removed"

  上面语句的等价形式为:

    if rm $TEMPDIR/*
    then
      :
    else
      echo "Files were not removed"
    fi
  这两种操作符可以联合使用,如在下面的命令行中,只有command1command2执行成功后,command3才会执行:

    command1 && command2 && command3

  下面的命令行表示只有command1成功执行,command2不成功执行时,才会执行command3

  &&||操作符可以简化命令条件执行的格式,但一般只用于一条命令的条件执行。如果许多命令都使用这两个操作符,那么整个程序的可读性将变的很差,所以在多条命令的条件执行时,最好采用可读性好的if语句。

函数

  现在我们介绍Shell程序中的函数部分,基本上任何高级语言都支持函数这个东西,能让我们胜好多事情的东西,至少省的频繁的敲击相同的东西,好了come
on

Shell
程序中的函数

  函数又叫做子程序,可以在程序中的任何地方被调用,其格式如下:

  函数名字()
  {
    command
    ... ...
    command;
  }

  Shell程序的任何地方都可以用命令
"
函数名字" 调用,使用函数的好处有两点,一点是使用函数可以把一个复杂的程序化为多个模块,易于管理,符合结构化程序的设计思想,另一个好处是代码的重用。

  Shell函数和Shel程序比较相似,它们的区别在于Shell程序在子Shell中运行,而Shell函数在当前Shell中运行。因此,在当前Shell中可以看到Shell函数对变量的修改。在任何Shell中都可以定义函数,包括交互式Shell

  例如:

    $dir() {ls -l;}

    结果是我们在$后面打dir,其显示结果同ls
-l
的作用是相同的。该dir函数将一直保留到用户从系统退出,或执行了如下所示的unset命令:
    $unset dir
    下面的例子说明了函数还可以接受位置参数:

    $dir(){_
    >echo "permission    ln owner   group    file sz last
access
    >ls -l $*;
    >}

    运行 dir a* 看产生什么结果

    参数a*传递到dir函数中并且代替了$*

    通常Shell程序将在子Shell中执行,该程序对变量的改变只在子Shell中有效而在当前Shell中无效。"."命令可以使Shell程序在当前Shell中执行。用户可以在当前Shell中定义函数和对变量赋值。通常用下面命令来重新初使化.profileShell环境的设置。
    $ . .profile
  由于看到这部分相对简单,我们还是顺便说说trap好了

使用trap命令进行例外处理

  用户编写程序在程序运行时可能会发生一些例外情况,比如执行该程序的用户按中断键或使用kill命令,或者控制终端突然与系统断开等。unix系统中的上述情况会使系统向进程发一个信号,通常情况下该信号使进程终止运行。有时侯用户希望进程在接到终止信号时进行一些特殊的操作。若进程在运行时产生一些临时文件,又因接受到的信号而终止。那么该进程产生的临时文件将保留下来。在bsh中,用户可以使用trap命令修改进程接收到终止信号时进行的默认操作。
  trap命令格式如下:

     trap command_string signals


多数系统中共有15种发给进程的信号,默认情况下大多数信号都会使程序终止。用户最好查阅自己系统的文挡,看看本系统内使用的信号种类。除了信号为9(真正的kill信号)不能使用trap命令外,其他信号所带来的操作都可以用trap命令进行指定。下面是trap命令中经常使用的几种信号:

    信号   功能
    
     1     挂起
     2    操作中断
     15    软终止(kill信号)

  若命令串中包含不只一条命令,必须使用引号将整个命令括起来,具体是单引号还是双引号,由用户是否需要变量替换决定。"
"
替换,' '不替换。

  使用下面trap命令可以使程序在接收到挂起、中断或kill信号时,首先把临时文件删除,然后退出:

    trap "rm $TEMPDIR/* $$;exit" 1 2 15

  在上面例子中,当Shell读取trap命令时,首先对$TEMPDIR$$进行变量替换,替换之后的命令串将被保存在trap表中,若上例中trap命令使用单引号时,trap命令执行时候,不进行变量替换,而把命令串 rm
$TEMPDIR/*
$$;exit
 放到trap表中,当检测到信号时,程序解释执行trap表中的命令串,此时进行变量替换。前面变量$TEMPDIR$$的值为执行trap指令时候的值,后一种情况中变量的值为程序接收到信号时候的值,所以
"
'一定要区分仔细。

  下面命令的含义为用户按二次中断键后,程序才终止:

    trap 'trap 2' 2

  一般trap命令中的命令串中几乎都包含exit语句,上面rm的例子若无exit语句,接收到信号rm命令执行完后程序将挂起。但有时用户也需要程序在接到信号后挂起,例如当终端和系统断开后,用户发出挂起信号,并执行空命令,如下:

    trap : 1

  若用户想取消前trap指令设置的命令串,可以再执行trap命令,在命令中不指定命令串表示接收到信号后进行默认的操作,命令如下:
    trap 1

规范Shell

获取UNIX类型的选项:

  unix有一个优点就是标准UNIX命令在执行时都具有相同的命令行格式:

  command -options parameters

  如果在执行Shell程序也采用上述格式,Bourne
Shell
中提供了一条获取和处理命令行选项的语句,即getopts语句。该语句的格式为:

  getopts option_string variable

  其中option_string中包含一个有效的单字符选项。若getopts命令在命令行中发现了连字符,那么它将用连字符后面的字符同option_string相比较。若有匹配,则把变量variable的值设为该选项。若无匹配,则variable设为?。当getopts发现连字符后面没有字符,会返回一个非零的状态值。Shell程序中可以利用getopts的返回值建立一个循环。

  下面代码说明了date命令中怎么使用getopts命令处理各种选项,该程序除了完成unix的标准命令date的功能外,还增加了许多新的选项。
  #date程序
  if [ $# -lt 1 ]
  then
    date
  else
    while getopts mdyDHMSTJjwahr OPTION
    do
      case $OPTION
      in
        m)date '+%m';;
        d)date '+%d';;
        y)date '+%y';;
        D)date '+%D';;
        H0date '+%H';;
        M)date '+%M';;
        S)date '+%S';;
        T)date '+%T';;
        j)date '+%j';;
        J)date '+%y%j';;
        w)date '+%w';;
        a)date '+%a';;
        h)date '+%h';;
        r)date '+%r';;
        \?)echo "无效的选项!$OPTION";;
      esac
    done
  fi

有时侯选项中还带一个值,getopts命令同样也支持这一功能。这时需要在option_string中选项字母后加一个冒号。当getopts命令发现冒号后,会从命令行该选项后读取该值。若该值存在,那么将被存在一个特殊的变量OPTARG中。如果该值不存在,getopts命令将在OPTARG中存放一个问号,并且在标准错误输出上显示一条消息。

  下面的例子,实现拷贝一个文件,并给文件赋一个新的名字。-c选项指定程序拷贝的次数,-v选项要求显示新创建文件的文件名。

  #--拷贝程序

  COPIES=1
  VERBOSE=N
  while getopts vc:OPTION



阅读更多内容1 · 2 · 下一页>>


  上一篇: unix shell系列:Unix系列shell程...   下一篇: linux rpm问题:怎样查看rpm安装...
li
 §相关评论  
 热点文章

·新手强烈推荐:linux入门11点建
·Unix学习方法-走向高手之路
·Linux性能分析和调整的基本原则
·你很陌生但是很适用的10个linu
·Oracle补丁3028673,解决单进程
·最近被aix 5305给折腾死了
·在AIX 5L上配置NFS Server/Cli
·在AIX 5L上配置与管理路由
·这个补丁影响的范围还是比较大
·在AIX 5L上使用绑定网卡(ethe
·使用pam_abl防止SSH遭暴力破解
li
 编辑推荐
·新手强烈推荐:linux入门11点建
·Unix学习方法-走向高手之路
·Linux性能分析和调整的基本原则
·你很陌生但是很适用的10个linu
·Oracle补丁3028673,解决单进程
·最近被aix 5305给折腾死了
·在AIX 5L上配置NFS Server/Cli
·在AIX 5L上配置与管理路由
·这个补丁影响的范围还是比较大
·在AIX 5L上使用绑定网卡(ethe
·使用pam_abl防止SSH遭暴力破解
li
 相关篇章
·unix shell系列:Unix系列shell程...
·unix shell教程:Unix系列shell程...
·经验总结:Solaris性能优化
·强烈推荐:rhcs 4.2+gfs6.1.2安...
·shell扫盲篇:Shell常见知识
·shell基础系列:awk 用法
·shell最适用东西:awk实用手册
·知识总结:Sed简明速查手册
·诚邀您参加Linux爱好者技术聚会
·Solaris 10 配置双网卡双网关出口
·linux rpm问题:怎样查看rpm安装...
·AIX5.1L下安装bash
·linux问题小结:关于root不能登录...
·VMware Server上安装linux步骤详...
·linux系统守护进程:crontab基本...
·新手强烈推荐:linux入门11点建议
·linux援救模式:linux rescue使用...
·Redhat Linux inittab详解
·推荐:AIX常用命令总结
·IBM RS/6000 AIX操作系统的安装
 
li
设为首页 | 关于我们 | 技术服务 | 收藏本站 | 网站地图 | 联系方式 | 本站友情连接