日历

« 2008-12-05  
 123456
78910111213
14151617181920
21222324252627
28293031   

我的好友

统计信息

  • 访问量: 925
  • 日志数: 27
  • 建立时间: 2008-04-06
  • 更新时间: 2008-04-18

RSS订阅

搜集资料,交流经验……

我的最新日志

  • freebsd4.2进单用户模式

    2008-4-18

    装FreeBSD4.2系统的硬盘,换了一台机器后,启动,直接进入单用户模式,没有提示用户名和密码,在原来的机器上却可以正常启动并可进入多用户,什么原因?

    Link URL: http://mytesting.bokee.com/viewdiary.15540028.html
  • 踏瑶娘(皮影戏)

    2008-4-18

    女:野花迎风飘摆,好像是在倾诉衷肠;绿草凄凄抖动,如无尽的缠绵依恋;初率的柳枝坠入悠悠碧水,搅乱了芳心柔情荡漾.为什么春天每年都如期而至,而我远行的丈夫却年年不见音信。

    男:离家去国整整三年,为了梦想中金碧辉煌的长安,都市里充满了神奇的历险,满足一个男儿宏伟的心愿。现在终于衣锦还乡,又遇上这故里的春天。看这一江春水,看这满溪桃花,看这如黛青山,都没有丝毫改变,也不知我新婚一个月就别离的妻子是否依旧红颜。

    男:来的是谁家女子,生得春光满面,美丽非凡?这位姑娘,请你停下美丽的脚步,你可知自己犯下什么样的错误?

    女:这位将军,明明是你的马蹄踢翻了我的竹篮,你看这宽阔的道路直通蓝天…
       你却非让这可恶的畜生溅起我满身污点,怎么反倒……怪罪起我的错误?

    男:您的错误就是美若天仙,蓬松的乌发涨满了我的眼帘,看不见道路山川,只是漆黑一片……

    女:…真的美若天仙?

    男:是的!你的错误就是美若天仙,你婀娜的身姿让我的手不听使唤,你蓬松的乌发涨满了我的眼帘,看不见道路山川,只是漆黑一片;你明艳的面颊让我胯下的这头畜生倾倒,竟忘记了他的主人是多么威严。



    Link URL: http://mytesting.bokee.com/viewdiary.15843742.html
  • 我们是糖,甜到哀伤(转)

    2008-4-18

    爱上她,就像儿时爱上糖一样,感觉怎么也爱不够,虽然明知道会有牙齿长虫的危险,但是,却仍然那么义无返顾。也许,别人无法理解,但是对于我来说,爱她已经像是习惯一样,已经像毒品上瘾一样,我无法让自己不去爱她。

     

    虽然她与我总是聚少离多,但是,那相聚时的热烈与分别后的相思就像一柄双刃剑一样,既给我甜蜜,也给我痛苦。让我难以忘却跟她在一起的分分秒秒,让我难以忘却跟她分离的岁岁年年。

     

    记得,刚开始爱上她的时候,我像个小孩子一样在她面前从不掩饰自己的喜怒哀乐,从不压抑和改变自己的倔强脾气,可是,慢慢的,在她面前我开始变得温顺,也许,是小时侯所学到的哲理改变了我:如果你要吃到糖,那么你就要珍惜好糖,不能让她在太阳底下融化。我爱上了她,那么就要像儿时那样去珍惜好糖。所以我要为她改变,虽然她一直对我不满意,但是我一直在努力,从来没有放弃修正自己。

     

    虽然她总是以我们之间年龄的差距来搪塞我,但是,我一直在努力地告诉她这样一个信念:如果是真爱,年龄不是问题。虽然我们无法去与世俗抗衡,但是我们可以自私一点,我们为了寻找属于自己的真正的幸福生活可以不去想那么多,可以不用像别人一样,把自己的生活当作戏剧一样演给别人看,我们只做自己的演员与观众,只演给自己看。但是她总是在强调爱情与婚姻不只是两个人的事情,而是两个家庭之间的事情。所以我们一直为此辩论不休。其实在这个世界上,无论以什么姿态,以什么高超的演技,把自己的生活演绎给别人看,可能我们已经很尽力了,但是,总会有人不满意,要么是我们自己,要么是我们的家人,要想做到十全十美,几乎是不可能的。那我们何必要去想那么多呢?我们只需要在乎我们在一起是否合适,是否幸福就够了。

     

    其实,糖也是这样,有时虽然糖衣很漂亮,但是我们吃起来却并不满意,因为那种糖并不适合我们的口味。每一个人都有自己不同的口味,所以,我们不必去追求糖衣的华丽,我们只需要选择适合自己口味的糖核就够了。追求生活的朴实无华与内在本质就像我们选糖和吃糖的过程一样。

     

    爱上她,感觉自己变成了糖一样,有甜滋滋的幸福,也有怕被阳光融化的惶恐,更有怕一不小心打翻她醋坛子的小心翼翼。虽然我知道她吃醋是在乎我爱我,但是,醋坛子终究会影响糖的甜蜜,终究会影响她的身体健康。我只想告诉她:爱你,已经成为我一生的职业,呵护你,已经是我今生所选择的梦想。无论我们之间有多么深的误会,请你不要轻易放弃我们的爱情,请你不要再轻易将分手说出口。要想糖能够甜蜜得更长久,最好的办法是将糖永远揣在手心里,但不要吃掉,也不要在一只手上揣得太久,偶儿换一只手,可能我们就能永远保持着想吃糖的欲望,永远保持着对糖的甜蜜的回忆。

     

    我们是糖,虽然我们的年龄无法让我们披一件美丽的糖衣,那也没有什么可惜的,毕竟我们是糖,我们有自己的甜蜜;毕竟我们是糖,我们已经融为了一体。虽然有争吵,但是要相信,糖分子永远在糖里,正如爱情永远在我们的心里一样。

     

    我们是糖,甜到哀伤,在每一个孤寂的夜晚,在每一个喧闹的白天,我都在回忆远在大洋彼岸的你,都在回忆你给我的甜蜜,请不要责怪我,请不要批评我,爱你,我愿意这样自我折磨。虽然,我不知道你是否还在为今天的事情生气,但是,看到你生气,我却是那么心急,却是那么心疼,也许你不相信,但是,那钻心的痛苦却让我无法入眠无法进食。我知道,我永远得罪不起你,因为我爱你,得罪了你,我就会受到你温柔而又野蛮的惩罚。

     

    此时此刻,我多想见到你,我多想伏在你的怀中痛哭一场,为我们爱情路上的艰辛,为我们爱情未来的迷茫……..

     

    我们是糖,甜到哀伤。在这个凄风冷雨的深夜,我不知道该用怎样的文字向你表白我内心的痛苦与绝望,因为爱你,我不能在阳光里歌唱我们的爱情,我们彼此只能躲在糖衣下,永远遮掩着我们的爱情,我们本来不是偷情,可是我们却比偷情的人还要小心翼翼。因为爱我,你不能挽着我的手徜徉在阳光里,我们彼此只有躲在阴影里,我们本来是相爱的恋人,可是我们却要避开所有人的眼睛。这是你忧伤,也是我的哀伤;是你的痛苦,也是我的迷茫。

     

    我们是糖,甜到哀伤。我多么希望你放弃对我的怨恨,我多么希望能听到你的声音,因为在这个凄风冷雨的深夜,你是我心里的阳光。




    Link URL: http://mytesting.bokee.com/viewdiary.15843674.html
  • unix下shell编程(三)

    2008-4-18

    Until语句

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


                      Until语句的结构如下:
                      until command
                        do
                          command
                          command
                          … …
                        done

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

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

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

                      shift命令执行前变量的值在shift命令执行后就不可用了。

                      示例如下:

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

                      结果显示如下:

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

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


                      #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 + `
                      shift
                      done
                      echo "sum is: $sum"

                      执行上述程序:

                      $x_shift2.sh 10 20 15

                      其显示结果为:

                      45

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


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

                        在熟悉了shift命令后,我们一起看看,Bsh程序中非常有用的for循环语句,这种循环同上面说的while和until循环不同,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"

                      中断循环指令

                        在程序循环语句中,我们有时候希望遇到某中情况时候结束本次循环执行下次循环或结束这个循环,这就涉及到两条语句:continue和break。continue命令可使程序忽略其后循环体中的其他指令,直接进行下次循环,而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程序中可以使用多种不同的方法完成相同的功能,例如until和while语句就可以完成相同的功能,同样,除了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
                        这两种操作符可以联合使用,如在下面的命令行中,只有command1和command2执行成功后,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中定义函数和对变量赋值。通常用下面命令来重新初使化.profile对Shell环境的设置。

                          $ . .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
                        do
                          case $OPTION
                          in
                            c)COPIES=$OPTARG;;
                            v)VERBOSE=Y;;
                            \?)echo "无效参数!"
                              exit 1;;
                          esac
                        done
                        if [ $OPTIND -gt $# ]
                        then
                          echo "No file name specified"
                           exit 2
                        fi
                        shift 'expr $OPTIND - 1'
                        FILE=
                        COPY=0
                        while [ $COPIES -gt $COPY ]
                        do
                          COPY='expr $COPY + 1'
                          cp $FILE $ $
                          if [ VERBOSE = Y }
                          then
                            echo $ $
                          fi
                        done

                      规范Shell:

                        我们知道环境变量PS1是提示符,看下面程序chdir:
                        if [ ! -d "$!" ]
                        then
                          echo " is not a directory"
                          exit 1
                        fi
                        cd
                        PS1="'pwd'>"
                        export PS1

                        我们执行:

                          $chdir /usr/ice666

                        结果提示符号变成/usr/ice666>了吗?没有,为什么?

                        原因在于:chdir在子Shell中执行,变量PS1的修改在当前Shell中也不会起作用,若要chdir完成意想中的功能,必须在当前Shell中执行该命令。最好的方法就是把其改成一个函数并且在.profile文件中定义。但若要把函数放到单个文件中并在当前Shell中执行,则需要使用

                      . 命令,并将chdir重写成一个函数,把其中的exit改写成return。下面代码是
                      .ice_ps的内容:

                        #--提示符
                        chdir()
                        {
                        if [ !-d "" ]
                        then
                          echo " is not a directory"
                          return
                        fi
                        cd
                        PS1="'pwd'>"
                        export PS1;
                        }

                        然后我们在.profile文件中加入下面语句

                        .ice_ps

                        然后在切换目录的时候,我们用chdir命令,结果是什么呢,自己实验好了!
                       
                      调试Shell程序

                      1>调试shell程序

                        用户刚编写完Shell程序中,不可避免的会有错误,这时我们可以利用Bsh中提供的跟踪选项,该选项会显示刚刚执行的命令及参数。用户可以通过set命令打开-x选项或在启动Shell使用-x选项将Shell设置成跟踪模式。例如有下面代码ice_tx:


                        if [ $# -eq 0 ]
                        then
                          echo "usage:sumints integer list"
                          exit 1
                        fi
                        sum=0
                        until [ $# -eq 0 ]
                        do
                          sum='expr $sum + '
                          shift
                        done
                        echo $sum

                        我们用跟踪模式运行:

                        $sh -x ice_tx 2 3 4
                        结果显示:
                        +[ 3 -eq 0 ]
                        +sum=0
                        +[ 3 -eq 0 ]
                        +expr 0+2
                        +sum=2
                        +shift
                        +[ 2 -eq 0 ]
                        +expr 2+3
                        +sum=5
                        +shift
                        +[ 1 -eq 0 ]
                        +expr 5+4
                        +sum=9
                        +[ 0 -eq 0 ]
                        +echo 9
                        9

                        从上面可以看出,跟踪模式下Shell显示执行的每一条命令以及该命令使用的变量替换后的参数值。一些控制字如if、then、until等没显示。


                      2>命令分组

                        Shell中若干命令可以组成一个单元一起执行。为了标识一组命令,这些命令必须放到"()"或"{}"中。放在"()"中的命令将在子Shell中运行,而放在"{}"中的命令将在当前Shell中运行。子Shell中运行的命令不影响当前Shell的变量。当前Shell中运行的命令影响当前Shell的变量。


                        $NUMBER=2
                        $(A=2;B=2;NUMBER='expr $A+$B';echo $NUMBER)
                        结果为:4
                        $echo $NUMBER
                        结果为:2
                        如果把上面的()变成{},结果会是怎么样的呢?

                      3>使用Shell分层管理器shl

                        UNIX是一个多道程序设计的操作系统,一些UNIX系统利用这一特性提供了Shell层次管理器shl。使用shl用户一次可以打开多个层次的Shell,其中活跃的Shell可以从终端上获得输入。但所有Shell的输出都可在终端上显示,除非显示被禁止。


                        多个Shell中有一个为shl,当用户在某个Shell中工作时,可以通过使用特殊字符(一般为Ctrl+z)返回shl。为了同其他Shell区别,shl中提示符为">>>"。当用户工作在Shell层次管理器中时,可以创建、激活和删除Shell,下面是shl中使用的命令。


                        create name    产生名为name的层次
                        delete name    删除名为name的层次
                        block name     禁止名为name的层次的输出
                        unblock name    恢复名为name的层次的输出
                        resume name    激活名为name的层次
                        toggle       激活近来经常使用的层次
                        name        激活名为name的层次

                        layers [-l] name 
                      对于表中的每个层次,显示其正在运行的进程的进程号,-l选项要求显示详细信息。

                        help        显示shl命令的帮助信息
                        quit        退出shl以及所有被激活的层次

                      总结

                        在前面我们主要介绍了sh的变量、基本语法、程序设计等。如果掌握了这些内容,在学习其他UNIX下编程语言的时候,相信有一定的好处,我们说了,在大多数的UNIX中都提供Bourn

                      Shell,而且很少有象sh这样强大的脚本编辑语言了,是系统管理员和程序员的一笔财富,并且不需要额外的软件环境,对文件等处理借助unix命令,实现起来比c实现还要简单。



    Link URL: http://mytesting.bokee.com/viewdiary.15819724.html
  • unix下shell编程(二)

    2008-4-18

    3>在Shell中使用数据变量

                        用户可以在Shell中使用数据变量,例如ba.sh程序:

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

                        该程序中要备份的目录为一常量,即该程序只能用来备份一个目录。若在该程序中使用变量,则会使其更通用:

                          workdir=
                          cd $workdir
                          ls * |cpio -o > /dev/fd0

                        通过这一改变,用户可以使用程序备份变量$workdir指定的目录。例如我们要备份/home/www的内容,只要运行ba.sh

                      /home/www即可实现。(若不明白
                      ,下面将详细介绍shell参数的传递,代表本sh程序-ba.sh的第一个参数)

                        4>在Shell程序中加上注释

                        为了增加程序的可读性,我们提倡加入注释。在Shell程序中注释将以"#"号开始。当Shell解释到"#"时,会认为从"#"号起一直到该行行尾为注释。


                        5>对Shell变量进行算术运算

                        高级语言中变量是具有类型的,即变量将被限制为某一数据类型,如整数或字符类型。Shell变量通常按字符进行存储,为了对Shell变量进行算术运算,必须使用expr命令。


                        expr命令将把一个算术表达式作为参数,通常形式如下:

                          expr [数字] [操作符] [数字]

                        由于Shell是按字符形式存储变量的,所以用户必须保证参加算术运算的操作数必须为数值。下面是有效的算术操作符:

                          +   两个整数相加
                          -   第一个数减去第二个数
                          *   两整数相乘
                          /   第一个整数除以第二个整数
                          %   两整数相除,取余数
                        例如:
                          $expr 2 + 1
                           结果显示:3
                          $expr 5 - 3
                           结果显示:2

                      若expr的一个参数是变量,那么在表达式计算之前用变量值替换变量名。
                          $int=3
                          $expr $int + 4
                          结果显示:7
                        用户不能单纯使用"*"做乘法,若输入:
                          $expr 4*5
                        系统将会报错,因为Shell看到"*"将会首先进行文件名替换。正确形式为:
                          $expr 4 \* 5
                           结果显示:20
                        多个算术表达式可以组合在一起,例如:
                          $expr 5 + 7 / 3
                          结果显示:7
                        运算次序是先乘除后加减,若要改变运算次序,必须使用"`"号,如:
                          $int=`expr 5 + 7`
                          $expr $int/3
                           结果显示:4
                          或者:
                          $expr `expr 5+7`/3
                          结果显示:4

                        6>向Shell程序传递参数

                        一个程序可以使用两种方法获得输入数据。一是执行时使用参数。另一种方法是交互式地获得数据。vi编辑程序可以通过交互式的方法获得数据,而ls和expr则从参数中取得数据。以上两种方法Shell程序都可以使用。在"交互式读入数据"一节中将介绍Shell程序通过交互式的方法获得参数。


                        通过命令行给Shell程序传递参数可以扩大程序的用途。以前面提到的ba.sh程序为例:
                        $cat >re.sh
                        cd $workdir
                        cpio -i < /dev/fd0
                        ^d

                        程序re.sh恢复了ba.sh程序备份的所有文件。若只从软盘上恢复一个指定的文件,可以用该文件名作为参数,传递给Shell程序re.sh:


                        程序改写如下:
                        $cat >re2.sh
                        cd $workdir
                        cpio -i < /dev/fd0
                        ^d

                        用户可以指定要恢复的文件,例如fname

                        $re2.sh fname

                      此时文件fname作为第一个位置参数传递给re2.sh,re2.sh的缺点是要恢复两个或多个文件要重复运行,我们可以用$*变量传递不确定的参数给程序:


                        $cat >re3.sh
                        cd $workdir
                        cpio -i $* < /dev/fd0
                        ^d

                        我们就可以恢复多个文件,例如fname1,fname2,fname3
                        $re3.sh fname1 fname2 fname3
                        (以上程序re.sh,re2.sh,re3.sh,假设用户已经chmod了可执行权利)

                        因为没有赋值的变量可以作为NULL看待,所以若是程序re3.sh在执行时候没赋予参数,那么一个空值将被插入到cpio命令中。该命令将恢复所有保存的文件。


                      条件判断语句

                        条件判断语句是程序设计语言中十分重要的语句,该语句的含义是当某一条件满足时,执行指定的一组命令。

                      1>if - then语句

                        格式: if command1
                           then
                             command2
                             command3
                           fi      ---(if 语句结束)
                             command4

                        每个程序或命令执行结束后都有一个返回的状态,用户可以用Shell变量$?获得这一状态。if语句检查前面命令执行的返回状态,若该命令成功执行,那么在then和fi之间的命令都将被执行。在上面的命令序列中,command1和command4总要执行。若command1成功执行,command2和command3也将执行。


                        请看下面程序:
                          #unload -program to backup and remove files
                          cd
                          ls -a | cpio -o > /dev/mnt0
                          rm *

                        该程序在备份资料后,删除档案,但当cpio命令不能成功执行时,rm命令还是把资料删除了,我们可不希望这样,为了避免此情况,可以用if

                      - then语句:
                          #--卸载和判断删除程序

                          cd
                          if ls -a | cpio > /dev/mnt0
                          then
                            rm *
                          fi
                        上面程序在cpio执行成功后才删除档案

                      同时,若执行没有成功,我们希望得到提示,sh中的echo命令可以向用户显示消息,并显示后换行,上面程序可以写成:
                           #--卸载和判断删除程序
                          cd
                          if ls -a | cpio > /dev/mnt0
                          then
                            echo "正删除文件资料... ..."
                            rm *
                          fi

                        echo命令可以使用一些特殊的逃逸字符进行格式化输出,下面是这些字符及其含义:

                          \b  Backspace
                          \c  显示后不换行
                          \f  在终端上屏幕的开始处显示
                          \n  换行
                          \r  回车
                          \t  制表符
                          \v  垂直制表符
                          \   反斜框
                          nnn 用1,2或3位8进制整数表示一个ASCII码字符

                      2>if - then - else语句

                        不用多说它的作用,别的高级语言中都有,格式为:
                        if command1
                        then
                          command2
                          command3
                        else
                          command4
                          command5
                        fi

                        在此结构中,command1中是先执行,当command1成功执行时,将执行command2和command3,否则执行command4和command5


                        注意看下面程序:
                          #备份程序
                          cd
                          if ls -a |cpio -o > /dev/mnt0
                          then
                            echo "删除源资料... ..."
                            rm *
                          else
                            echo "磁带备份失败!"
                          fi

                      3>test命令进行条件测试

                        if语句可以通过测试命令执行的返回状态来控制命令的执行,若要测试其他条件,在bsh中可以使用test命令。该命令检测某一条件,当条件为真时返回0,否则返回非0值。test命令可以使Shell程序中的if语句象其他程序语言中的条件判断语句一样,具有很强的功能。


                        test命令的使用方法为:
                          test condition
                        可测试的条件分为4类:
                        1)测试两个字符串之间的关系。
                        2)测试两个整数之间关系。
                        3)测试文件是否存在或是否具有某种状态或属性。
                        4)测试多个条件的与(and)或(or)组合。

                      1、条件语句>>test语句

                      1>测试字符串间的关系

                        bsh把所有的命令行和变量都看作字符串。一些命令如expr和test可以把字符当作数字进行操作。

                        同样任何数字也可以作为字符串进行操作。

                        用户可以比较两个字符串相等或不等,也可以测试一个串是否赋了值。有关串的操作符如下:
                          str1 = str2      当两个串有相同内容、长度时为真
                          str1 != str2      当串str1和str2不等时为真
                          -n str1        当串的长度大于0时为真(串非空)
                          -z str1        当串的长度为0时为真(空串)
                          str1         当串str1为非空时为真

                        不但Shell程序可以使用test进行条件判断,test命令也可以独立执行,如:

                          $str1=abcd
                          $test $str1 = abcd
                          $echo $?
                          结果显示:0

                      与上例中第一行赋值语句中的等号不同,test命令中的等号两边必须要有空格。本例test命令共有3个参数。注意两个串相等必须是长度和内容都相等。


                          $str1="abcd "
                          $test "$str1" = abcd
                          $echo $?
                          结果显示:1

                        上面str1包含5个字符,其中最后一个为空格符。而test命令中的另一个串只有4个字符,所以两串不等,test返回1。

                        不带任何操作符和使用-n操作符测试一个串结果是一样的,例如:

                          $str1=abce
                          $test $str1
                          $echo $?
                          结果显示:0    
                          $test -n $str1
                          $echo $?
                          结果显示:0

                        但是,上面两条命令也有一点差别,反映出了使用test命令潜在的问题,请看下例:

                          $str1="   "
                          $test $str1
                          $echo $?
                          结果显示:1
                          $test -n "$str1"
                          $echo $?
                          结果显示:0
                          $test -n $str1
                          结果显示:test:argument expected

                        上例中,第一次测试为假因为Shell在执行命令行之前首先要进行变量替换,即把$str1换成空格,然后shell又将命令行上的空格删除,故test命令测试到的为空串。而在第二次测试中,变量替换后空格位于括号内,故不会被删除,test测试到的是一个包含空格的串,在第三次测试中,shell把空格删除,只把-n传个test命令,所以显示参数错。


                      2>测试两个整数之间关系

                        test命令与expr命令一样,也可以把字符转变成整数,然后对其操作。test命令对两个数进行比较,使用的操作符如下:

                          int1 -eq int2    两数相等为真
                          int1 -ne int2    两数不等为真
                          int1 -gt int2    int1大于int2为真
                          int1 -ge int2    int1大于等于int2为真
                          int1 -lt int2    int1小于int2为真
                          int1 -le int2    int1小于等于int2为真

                        下面的例子反映了字符串比较与数字比较的不同:

                          $str1=1234
                          $str2=01234
                          $test $str1 = $str2
                          $echo $?
                          结果显示:1
                          $test $str1 -eq $str2
                          $echo $?
                          结果显示:0

                      3>有关文件的测试

                        使用test进行的第三类测试是测试文件的状态,用户可以测试文件是否存在,是否可写以及其他文件属性。下面是文件测试时使用的选项。注意只有文件存在时,才有可能为真。


                        -r file     用户可读为真
                        -w file     用户可写为真
                        -x file     用户可执行为真
                        -f file     文件为正规文件为真
                        -d file     文件为目录为真
                        -c file     文件为字符特殊文件为真
                        -b file     文件为块特殊文件为真
                        -s file     文件大小非0时为真
                        -t file     当文件描述符(默认为1)指定的设备为终端时为真
                      4>复杂的条件测试(and 、or 、not)
                        -a         与
                        -o        或
                        !        非
                        就是组合条件了,任何高级语言中都有的(NOT 、AND 、OR),例如:
                          $test -r em.null -a -s em.null
                          $echo $?
                          结果显示:1
                          说明了em.null并不是可读并且非空的文件

                      5>另一种执行test的方法

                        bsh中还有另一种执行test命令的方法,就是把测试条件放到一对[
                      ]中,例如:
                          $int1=4
                          $[ $int1 -gt 2 ]
                          $echo $?
                          结果显示:0

                      要注意在[ 的后面和 ]符号的前面要有一个空格。
                        下面我们用test命令写个简单但比较完善的程序:

                          #-- 备份程序
                        
                          #-- 检查参数
                          if [ $# -ne 1 ]
                          then

                            echo "请在程序名后面指出要备份文件所在目录!"
                            exit 1
                          fi
                          #-- 检查目录名是否有效
                          if [ !-d "" ]
                          then
                            echo " 不是一个目录!"
                            exit 2
                          fi
                          cd
                          ls -a | cpio -o >/dev/mnt0
                          if [ $? -eq 0 ]
                          then
                            rm *
                          else
                            echo "cpio执行不成功!备份失败..."
                            exit 3
                          fi

                      6>空命令

                        在Bsh中用 : 代表空命令,就是充个数,什么都不做

                      7>嵌套if语句和elif结构

                        检查条件1
                        A:当条件1为真,则执行一部分操作
                        B:若条件1为假,检查条件2
                          1)若条件2为真,执行另外一部分操作
                          2)若条件2为假,检查条件3
                          3)若条件3为真,执行其他一部分操作
                        语法如下:
                          if command
                          then
                            command
                          else
                            if command
                            then
                              command
                            else
                              if command
                              then
                                command
                              fi
                            fi
                          fi

                      8>elif语句

                        嵌套if语句有时会给用户带来混乱,特别是什么时候fi语句很难判断。因此Bourne
                      Shell又提供了elif语句。elif是else-if的缩写,它表示是if语句的继续。格式为:

                          if command
                          then
                            command
                          elif command
                          then
                            command
                          elif command
                          then
                            command
                          fi

                        上面介绍的嵌套if语句和elif语句完成相同的功能,用户可以根据自己的喜好选择一种使用。

                      9>case语句

                        前面说的elif语句替代if-then-else语句,但有时在编程时还会遇到对同一变量进行多次的测试,该情况可以用多个elif语句实现,但还有一种更简单的方法就是用case语句。


                        case语句不但取代了多个elif和then语句,还可以用变量值对多个模式进行匹配,当某个模式与变量值匹配后,其后的一系列命令将被执行,下面是case语句使用的语句。


                        case value in
                         pattem 1)
                          command
                          command;;
                         pattem 2)
                          command
                          command;;
                         ....
                         pattem)
                          command;
                        esac

                        case语句只执行其中的一组命令,当变量值与多个模式相匹配时,只有第一个匹配的模式对应的命令被执行。";;"表示该模式对应的命令部分程序。


                        通过学习下面的read语句,我们们再举例子说明case语句的用法。

                      10>read语句

                        Shell程序不但可以通过命令行参数得到输入数据,还可以使用read命令提示用户输入数据,其语法格式为:

                        read var1 var2... ...varn

                      当Bsh遇到一个read语句时,在标准输入文件中读取数据直到一个换行符。此时Shell在解释输入行时,不进行文件名或变量的替换,只是简单地删除多余的空格。然后Shell将输入行的第一个字的内容给变量1,第二个给变量2,直到所有变量都赋上值或是输入行为空。若输入行中字的个数超过变量个数,Shell将把输入行中剩余的所有字的内容都赋给最后一个变量。当变量个数多于输入行字的个数时候,多于的变量将赋一个空值。输入行的每一个字是由空格分隔的一个字母和数字组成的字符串。


                        $read var1 var2 var3
                          输入:Hello my friend
                        
                        $echo $var1 $var2 $var3
                          结果显示:Hello my friend
                        $echo $var2
                          结果显示:my

                      下面用个read和case的例子结束本部分的学习:

                        #--交互式备份,恢复程序
                        echo "输入要备份文件所在目录:\c"
                        read WORKDIR
                        if [ !-d $WORKDIR ]
                        then
                          echo "Sorry,$WORKDIR is not a directory"
                          exit 1
                        fi
                        cd $WORKDIR
                        echo "输入选择:"
                        echo _
                        echo "1.恢复到 $WORKDIR"
                        echo "2.备份 $WORKDIR"
                        echo "0.退出"
                        echo
                        echo "\c"
                        read CHOICE
                        case "$CHOICE" in
                         1)echo "恢复中... ..."
                          cpio -i < /dev/mnt0;;
                         2)echo "备份中... ..."
                          ls | cpio -o > /dev/mnt0;;
                         0)exit 1
                         *)exit 1
                        esac
                        if [ $? -ne 0 ]
                        then
                         echo "程序运行中出现错误!"
                        else
                         echo "操作成功!"
                        fi  
                       
                        在上面代码中,"*"定义了其他模式下不匹配时的默认操作。

                      循环语句

                        前面介绍的程序和所学的语句都是从头到尾成一条主线下来,或是成分支结构,在日常管理UNIX的过程中,经常要重复的做一些操作,处理批量的问题,这就涉及到了循环结构,同高级语言相似,UNIX的Shell也提供了强大的循环处理语句。


                        Bsh语言中有三种循环语句-while循环、until循环、for循环,下面通过具体的例子分别介绍这三种结构。

                      While循环

                        在while循环语句中,当某一条件为真时,执行指定的命令。语句的结构如下:

                      while command
                      do
                        command
                        command
                        … …
                      done

                      示例代码如下:

                      #测试while循环小程序

                      x_t=1
                        while [ $x_t -lt 5 ]
                        do
                           mm=` expr $x_t \* $int `  #注意"\"的作用
                           echo "$mm"
                           x_t=` expr $x_t + 1 `   #注意expr的用法
                        done
                        echo "THE WHILE IS END!\n"

                      程序的执行结果如下:
                      1
                      4
                      9
                      16
                      THE WHILE IS END

                        在上述程序中,当变量x_t的值小于5的时候,执行while循环中的语句。在第五次循环时,
                      [ $x_t-lt5]命令返回非零值,于是程序执行done后面的代码。
                      现在利用while循环,可以改进我们早些时候用的备份数据的例子,当用户指定的目录备份完毕后,使用while循环使程序执行一次可以备份多个用户指定的目录。代码如下:


                      echo "欢迎使用备份小程序"

                        ANS=Y
                        while [ $ANS = Y -o $ANS = y ]
                        do
                          echo _
                          #读目录名
                          echo "输入要备份的目录名:\c"
                          read DIR
                          if [ ! -d $DIR ]
                          then
                              echo "$DIR不是一个目录!"
                              exit 1
                          fi
                          cd $DIR
                          echo "请选择:"
                          echo _
                          echo "1 恢复数据到 $DIR"
                          echo "2 备份$DIR的数据"
                          echo
                          echo "请选择:\c"
                          read CHOICE
                          case "$CHOICE" in
                             1) echo "恢复中… …"
                              cpio -i        2) echo "备份中… …"
                              cpio -o >/dev/rmt0;;
                             *) echo "选择无效"
                          esac
                          if [ $? -ne 0 ]
                          then
                             echo "cpio执行过程中出现问题"
                             exit 2
                          fi
                          echo "继续别的目录吗?(Y/y)\c"
                          read ANS
                        done

                        在程序开始,我们给变量ANS符值为Y,根据whlie的判断条件,程序进入while循环,执行do-done中的语句,每次循环都要求用户输入ANS的值用来判断是否进行下次重复执行do-done中的语句。如果用户输入的条件不满足while语句条件,循环结束,程序执行done后面的语句。

     

     

     



    Link URL: http://mytesting.bokee.com/viewdiary.15819720.html
Open Toolbar