LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: ykwj121

【Bourne shell编程入门及脚本测试[转帖]】

[复制链接]
发表于 2009-2-19 21:23:41 | 显示全部楼层
37531679  请加入 linux 讨论群
回复 支持 反对

使用道具 举报

发表于 2010-3-22 17:40:09 | 显示全部楼层
好东西 , 谢谢分享!
回复 支持 反对

使用道具 举报

发表于 2010-3-26 13:19:27 | 显示全部楼层
Post by ykwj121;131595
发信人: Altmayer (alt>>追求>>堕落>>极限>>), 信区: GNULinux
标  题: Bourne Shell及shell编程(1)
发信站: 饮水思源 (2001年12月30日00:21:48 星期天), 站内信件
  
【 以下文字转载自 Altmayer 的信箱 】
【 原文由 Altmayer.bbs@altmayer.dhs.org 所发表 】
来  源: from altmayer.dhs.org ([211.80.41.106])
日  期: Sun Dec 30 00:20:35 2001
  
标  题: LINUX选修课讲义:Bourne Shell及shell编程(1)
发信站: 碧海青天 (Wed Apr 21 23:41:45 1999), 转信
  
版权声明:
    本文内容为大连理工大学LINUX选修课讲义,欢迎大家转载,但禁止使用本材料进行
    任何商业性或赢利性活动。转载时请保留本版权声明。
  
    作者:何斌武,hbwork@dlut.edu.cn,大连理工大学网络中心,April 1999.
  
    URL: ftp://ftp.dlut.edu.cn/pub/PEOPLE/albin/

/********抱歉,为了格式不乱,我就用代码模式粘贴了*********/

  1. ------------------------------------------------------------------------------
  2. Bourne Shell
  3.   
  4. 介绍:Bourne Shell 基础及其他很多有用的特性,shell编程及组织。
  5.   
  6. 主要内容:
  7. .shell基础      基本介绍,环境,选项,特殊字符
  8. .shell变量      用户定义变量,环境变量,位置变量(shell 参数)
  9. .shell script编程
  10.         条件测试,循环及重复控制
  11. .shell定制
  12.   
  13. 1.shell基础知识
  14.   作者:Stephen Bourne 在Bell实验室开发
  15.   建议:man sh  查看相关UNIX上的改进或特性
  16.   
  17. (1)shell提示符及其环境
  18.    /etc/passwd文件
  19.    提示符:$
  20.    /etc/profile $HOME/.profile
  21. (2)shell执行选项
  22.    -n   测试shell script语法结构,只读取shell script但不执行
  23.    -x   进入跟踪方式,显示所执行的每一条命令,用于调度
  24.    -a   Tag all variables for export
  25.    -c "string"  从strings中读取命令
  26.    -e   非交互方式
  27.    -f   关闭shell文件名产生功能
  28.    -h   locate and remember functions as defind
  29.    -i   交互方式
  30.    -k   从环境变量中读取命令的参数
  31.    -r   限制方式
  32.    -s   从标准输入读取命令
  33.    -t   执行命令后退出(shell exits)
  34.    -u   在替换中如使用未定义变量为错误
  35.    -v   verbose,显示shell输入行
  36.   
  37.    这些选项可以联合使用,但有些显然相互冲突,如-e和-i.
  38.   
  39. (3)受限制shell(Restircted Shell)
  40.     sh -r 或 /bin/rsh
  41.   
  42.     不能执行如下操作:cd, 更改PATH,指定全路径名,输出重定向,因此可以提供一个较
  43.     好的控制和安全机制。通常rsh用于应用型用户及拨号用户,这些用户通常是看不到提
  44.     示符的。通常受限制用户的主目录是不可写的。
  45.   
  46.     不足:如果用户可以调用sh,则rsh的限制将不在起作用,事实上如果用户在vi及more
  47.         程序中调用shell,而这时rsh的限制将不再起作用。
  48.   
  49. (4)用set改变 shell选项
  50.    用户可以在$提示符下用set命令来设置或取消shell的选项。使用-设置选项,+取消相应
  51.    选项,大多数UNIX系统允许a,e,f,h,k,n,u,v和x的开关设置/取消。
  52.   
  53.    set -xv
  54.         启动跟踪方式;显示所有的命令及替换,同样显示输入。
  55.    set -tu
  56.         关闭在替换时对未定义变量的检查。
  57.   
  58.    使用echo $-显示所有已设置的shell选项。
  59.   
  60.   
  61. (5)用户启动文件 .profile
  62.         PATH=$PATH:/usr/loacl/bin; export PATH
  63.   
  64. (6)shell环境变量
  65.         CDPATH  用于cd命令的查找路径
  66.         HOME    /etc/passwd文件中列出的用户主目录
  67.         IFS     Internal Field Separator,默认为空格,tab及换行符
  68.         MAIL    /var/mail/$USERNAME     mail等程序使用
  69.         PATH
  70.         PS1,PS2        默认提示符($)及换行提示符(>)
  71.         TERM    终端类型,常用的有vt100,ansi,vt200,xterm等
  72.   
  73.         示例:$PS1="test:";export PS1
  74.               test: PS1="\$";export PS1
  75.               $echo $MAIL
  76.               /var/mail/username
  77. (7)保留字符及其含义
  78. $      shell变量名的开始,如$var
  79.    |    管道,将标准输出转到下一个命令的标准输入
  80.    #    注释开始
  81.    &    在后台执行一个进程
  82.    ?   匹配一个字符
  83.    *    匹配0到多个字符(与DOS不同,可在文件名中间使用,并且含.)
  84.    $-   使用set及执行时传递给shell的标志位
  85.    $!   最后一个子进程的进程号
  86.    $#   传递给shell script的参数个数
  87.    $*   传递给shell script的参数
  88.    $@   所有参数,个别的用双引号括起来
  89.    $?   上一个命令的返回代码
  90.    $0   当前shell的名字
  91.    $n    (n:1-) 位置参数
  92.    $$   进程标识号(Process Identifier Number, PID)
  93.    >file        输出重定向
  94.    <file        输入重定向
  95.    `command`    命令替换,如    filename=`basename /usr/local/bin/tcsh`
  96.    >>fiile      输出重定向,append
  97.   
  98.    转义符及单引号:
  99.         $echo "$HOME $PATH"
  100.         /home/hbwork /opt/kde/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:
  101.         $echo '$HOME $PATH'
  102.         $HOME $PATH
  103.         $echo \$HOME $PATH
  104.         $HOME /opt/kde/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/hbw
  105. ork/bin
  106.   
  107.    其他:
  108.         $dir=ls
  109.         $$dir
  110.         $alias dir ls
  111.         $dir
  112.   
  113.         ls > filelist
  114.         ls >> filelist
  115.         wc -l < filelist
  116.         wc -l filelist
  117.         sleep 5; echo 5 seconds reaches; ls -l
  118.         ps ax |egrep inetd
  119.         find / -name core -exec rm {} \; &
  120.         filename=`date "+%Y%m%d"`.log
  121.   
  122. 2. shell变量
  123.   变量:代表某些值的符号,如$HOME,cd命令查找$HOME,在计算机语言中可以使用变量可以
  124.         进行多种运算和控制。
  125.   
  126.   Bourne Shell有如下四种变量:
  127.         .用户自定义变量
  128.         .位置变量即 shell script之参数
  129.         .预定义变量(特殊变量)
  130.         .环境变量(参考shell定制部分)
  131. (1)用户自定义变量(数据的存储)
  132.         $ COUNT=1
  133.         $ NAME="He Binwu"
  134.   
  135.      技巧:因为大部分UNIX命令使用小写字符,因此在shell编程中通常使用全大写变量,
  136.         当然这并不是强制性的,但使用大写字符可以在编程中方便地识别变量。
  137.   
  138.      变量的调用:在变量前加$
  139.         $ echo $HOME
  140.         /home/hbwork
  141.         $ WEEK=Satur
  142.         $ echo Today is $WEEKday
  143.         Today is
  144.         $echo Today is ${WEEK}day
  145.         Today is Saturday
  146.   
  147.      Shell变量赋值从右从左进行(Linux Shell/bash从左向右赋值!)
  148.      $ X=$Y Y=y
  149.      $ echo $X
  150.      y
  151.      $ Z=z Y=$Z
  152.      $ echo $Y
  153.   
  154.      $
  155.   
  156.      使用unset命令删除变量的赋值
  157.      $ Z=hello
  158.      $ echo $Z
  159.      hello
  160.      $ unset Z
  161.      $ echo $Z
  162.   
  163.      $
  164.   
  165.      有条件的命令替换
  166.         在Bourne Shell中可以使变量替换在特定条件下执行,即有条件的环境变量替换。
  167.         这种变量替换总是用大括号括起来的。
  168.   
  169.         .设置变量的默认值
  170.             在变量未赋值之前其值为空。Bourne Shell允许对变量设置默认值,其格式如
  171. 下:
  172.             ${variable:-defaultvalue}
  173.             例:
  174.                 $ echo Hello $UNAME
  175.                 Hello
  176.                 $ echo Hello ${UNAME:-there}
  177.                 Hello there
  178.                 $ echo $UNAME   #变量值并未发生变化
  179.   
  180.                 $ UNAME=hbwork
  181.                 $ echo Hello ${UNAME:-there}
  182.                 Hello hbwork
  183.                 $
  184.         .另一种情况:改变变量的值,格式如下:
  185.             ${variable:=value}
  186.   
  187.             例:
  188.                 $ echo Hello $UNAME
  189.                 Hello
  190.                 $ echo Hello ${UNAME:=there}
  191.                 Hello there
  192.                 $ echo $UNAME   #变量值并未发生变化
  193.                 there
  194.                 $
  195.         .变量替换中使用命令替换
  196.                 $USERDIR=${$MYDIR:-`pwd`}
  197.   
  198.         .在变量已赋值时进行替换  ${variable:+value}
  199.         .带有错误检查的有条件变量替换
  200.           ${variable:?value}
  201.           例:
  202.           $ UNAME=
  203.           $ echo ${UNAME:?"UNAME has not been set"}
  204.           UNAME: UNAME has not been set
  205.           $ echo ${UNAME:?}
  206.           UNAME: parameter null or not set
  207.   
  208.   (2)位置变量(Shell参数)
  209.   在shell script中位置参数可用$1..$9表示,$0表示内容通常为当前执行程序的文件名。
  210.   .防止变量值被替换 readonly variable
  211.   .使用export命令输出变量,使得变量对子shell可用,当shell执行一下程序时,shell
  212.    将为其设置一个新的环境让其执行,这称之了subshell.  在Bourne Shell中变量通常
  213.    被认为是本地变量,也就是说在对其赋值之外的shell环境之外是不认识此变量的。使
  214.    用export对subshell可用。
  215.   
  216.    例:对变量PS1的export操作,shell的提示符将发生变化。
  217.    $ PS1=`hostname`$
  218.         peony$sh
  219.         $ echo $PS1
  220.         $  <-输出结果
  221.         $ exit
  222.         peony$export PS1
  223.         peony$sh
  224.         peony$ echo $PS1
  225.         peony$  <-输出结果
  226.         peony$
  227.   
  228.   
  229. 3.Shell Script编程
  230. 目的:使用UNIX所提供的最常用工具来完成所需复杂任务的强大功能。
  231.   
  232. (1)最简单的Shell 编程
  233.    $ls -R / |grep myname |more
  234.   
  235.    每天数据的备份:
  236.    $ cd /usr/yourname; ls * |cpio -o > /dev/rmt/0h
  237.   
  238.    书写程序的目的是一次编程,多次使用(执行)!
  239.   
  240.    $ cat > backup.sh
  241.    cd /home/hbwork
  242.    ls * | cpio -o > /dev/rmt/0h
  243.    ^D
  244.   
  245.    执行:
  246.    $ sh backup.sh
  247.   
  248.    或:
  249.    $ chmod +x backup.sh
  250.    $ ./backup.sh
  251.   
  252.    技巧:在shell script中加入必要的注释,以便以后阅读及维护。
  253.   
  254. (2)shell是一个(编程)语言
  255.   同传统的编程语言一样,shell提供了很多特性,这些特性可以使你的shell script
  256.   编程更为有用,如:数据变量、参数传递、判断、流程控制、数据输入和输出,子
  257.   程序及以中断处理等。
  258.   
  259.   . 在shell编程中使用数据变量可以将程序变量更为通用,如在上面backup.sh中:
  260.     cd $WORKDIR
  261.     ls * | cpio -o > /dev/rmt/0h
  262.   
  263.   . Shell编程中的注释以#开头
  264.   . 对shell变量进行数字运算,使用expr命令
  265.         expr integer operator integer
  266.         其中operator为+ - * / %, 但对*的使用要用转义符\,如:
  267.         $expr 4 \* 5
  268.         20
  269.         $int=`expr 5 + 7`
  270.         $echo $int
  271.         12
  272.   
  273. (3)Shell编程的参数传递, 可通过命令行参数以及交互式输入变量(read)
  274.   
  275.      restoreall.sh 对backup.sh程序的备份磁带进行恢复
  276.         $cat > restoreall.sh
  277.         cd $WORKDIR
  278.         cpio -i < /dev/rmt/0h
  279.         ^D
  280.      restore1.sh:只能恢复一个文件
  281.         #restore1 --program to restore a single file
  282.         cd $WORKDIR
  283.         cpio -i $i < /dev/rmt/0h
  284.   
  285.         $restore1 file1
  286.   
  287.         恢复多个文件restoreany :
  288.         #restoreany --program to restore a single file
  289.         cd $WORKDIR
  290.         cpio -i $* < /dev/rmt/0h
  291.   
  292.         $ restoreany file1 file2 file3
  293.   
  294.   
  295. (4)条件判断
  296.    . if-then语句,格式如下:
  297.         if command_1
  298.         then
  299.                 command_2
  300.                 command_3
  301.         fi
  302.         command_4
  303.   
  304.    在if-then语句中使用了命令返回码$?,即当command_1执行成功时才执行command_2和
  305.    command_3,而command_4总是执行.
  306.   
  307.    示例程序unload: 在备份成功时删除原始文件,带有错误检查
  308.   
  309.         cd $1
  310.         #备份时未考虑不成功的情况!
  311.         ls -a | cpio -o > /dev/rmt/0h
  312.         rm -rf *
  313.   
  314.         改进如下:
  315.   
  316.         #当使用了管道命令时,管理命令的返回代码为最后一个命令的返回代码
  317.         if ls -a | cpio -o > /dev/rmt/0h
  318.         then
  319.                 rm -rf *
  320.         fi
  321.   
  322.    . if-then-else语句
  323.         if command_1
  324.         then
  325.                 command_2
  326.         else
  327.                 command_3
  328.         fi
  329.   
  330.         技巧: 由于shell对命令中的多余的空格不作任何处理,一个好的程序员会用这一特

  331.               对自己的程序采用统一的缩进格式,以增强自己程序的可读性.
  332.   
  333.     . 使用test命令进行进行条件测试
  334.       格式: test conditions
  335.   
  336.       test在以下四种情况下使用: a. 字符比较 b.两个整数值的比较
  337.                 c. 文件操作,如文件是否存在及文件的状态等
  338.                 d. 逻辑操作,可以进行and/or,与其他条件联合使用
  339.   
  340.       a. 测试字符数据: shell变量通常民政部下均作为字符变量
  341.         str1 = str2     二者相长,相同
  342.         str1 != str2    不同
  343.         -n string       string不为空(长度不为零)
  344.         -z string       string为空
  345.         string          string不为空
  346.   
  347.         例:
  348.                 $ str1=abcd     #在含有空格时必须用引号括起来
  349.                 $ test $str1=abcd
  350.                 $ echo $?
  351.                 0
  352.                 $ str1="abcd "
  353.                 $ test $str1=abcd
  354.                 $ echo $?
  355.                 1
  356.         Note: 在test处理含有空格的变量时最好用引号将变量括起来,否则会出现错误的
  357. 结果,
  358.               因为shell在处理命令行时将会去掉多余的空格,而用引号括起来则可以防止
  359.               shell去掉这些空格.
  360.               例:
  361.                 $ str1="    "
  362.                 $ test $str1
  363.                 $ echo $?
  364.                 1
  365.                 $ test "$str1"
  366.                 $ echo $?
  367.                 0
  368.                 $ test -n $str1
  369.                 test: argument expected
  370.                 $ test -n "$str1"
  371.                 $ echo $?
  372.                 0
  373.                 $
  374.   
  375.       b. 整数测试: test与expr相同,可以将字符型变量转换为整数进行操作,expr进行
  376.          整数的算术运算,而test则进行逻辑运算.
  377.   
  378.          表达式                 说明
  379.          ---------------------------------------
  380.          int1 -eq int2          相等?
  381.          int1 -ne int2          不等?
  382.          int1 -gt int2          int1 > int2 ?
  383.          int1 -ge int2          int1 >= int2 ?
  384.          int1 -lt int2          int1 < int2 ?
  385.          int1 -le int2          int1 <= int2 ?
  386.   
  387.          例:
  388.                 $ int1=1234
  389.                 $ int2=01234
  390.                 $ test $int1 -eq $int2
  391.                 $ echo $?
  392.                 0
  393.   
  394.       c. 文件测试:检查文件状态如存在及读写权限等
  395.   
  396.          -r filename     用户对文件filename有读权限?
  397.          -w filename     用户对文件filename有写权限?
  398.          -x filename     用户对文件filename有可执行权限?
  399.          -f filename     文件filename为普通文件?
  400.          -d filename     文件filename为目录?
  401.          -c filename     文件filename为字符设备文件?
  402.          -b filename     文件filename为块设备文件?
  403.          -s filename     文件filename大小不为零?
  404.          -t fnumb        与文件描述符fnumb(默认值为1)相关的设备是一个终端设备?
  405.   
  406.       d. 测试条件之否定,使用!
  407.         例:
  408.                 $ cat /dev/null > empty
  409.                 $ test -r empty
  410.                 $ echo $?
  411.                 0
  412.                 $ test -s empty
  413.                 1
  414.                 $ test ! -s empty
  415.                 $ echo $?
  416.                 0
  417.       e. 测试条件之逻辑运算
  418.         -a      And
  419.         -o      Or
  420.   
  421.         例: $ test -r empty -a -s empty
  422.             $ echo $?
  423.             1
  424.       f. 进行test测试的标准方法
  425.          因为test命令在 shell编程中占有很重要的地位,为了使shell能同其他编程语言
  426. 一样
  427.          便于阅读和组织, Bourne Shell在使用test测试时使用了另一种方法:用方括号将
  428. 整个
  429.          test测试括起来:
  430.   
  431.          $ int1=4
  432.          $ [ $int1 -gt 2 ]
  433.          $ echo $?
  434.          0
  435.   
  436.          例: 重写unload程序,使用test测试
  437.          #!/bin/sh
  438.          #unload - program to backup and remove files
  439.          #syntax: unload directory
  440.   
  441.          #check arguments
  442.          if [ $# -ne 1 ]
  443.          then
  444.                 echo "usage: $0 directory"
  445.                 exit 1
  446.          fi
  447.   
  448.          #check for valid directory name
  449.          if [ ! -d "$1" ]
  450.          then
  451.                 echo "$1 is not a directory"
  452.                 exit 2
  453.          fi
  454.   
  455.          cd $1
  456.   
  457.          ls -a | cpio -o > /dev/rmt/0h
  458.   
  459.          if [ $? -eq 0 ]
  460.          then
  461.                 rm -rf *
  462.          else
  463.                 echo "A problem has occured in creating backup"
  464.                 echo "The directory will not be ereased"
  465.                 echo "Please check the backup device"
  466.                 exit 3
  467.          fi
  468.          # end of unload
  469.   
  470.          在如上示例中出现了exit, exit有两个作用:一是停止程序中其他命令的执行,二

  471.          设置程序的退出状态
  472.   
  473.       g. if嵌套及elif结构
  474.         if command
  475.         then
  476.                 command
  477.         else
  478.                 if command
  479.                 then
  480.                         command
  481.                 else
  482.                         if command
  483.                         then
  484.                                 command
  485.                         fi

  486.                 fi
  487.         fi
  488.   
  489.         改进:使用elif结构
  490.         if command
  491.         then
  492.                 command
  493.         elif    command
  494.         then
  495.                 command
  496.         elif    command
  497.         then
  498.                 command
  499.         fi
  500.   
  501.         elif结构同if结构类似,但结构更清淅,其执行结果完全相同.
复制代码

--
※ 转寄:·极乐世界 altmayer.dhs.org·[FROM: NIRVANA]
有远见,有内容,谢谢
回复 支持 反对

使用道具 举报

发表于 2010-4-1 21:26:51 | 显示全部楼层
真是好东西啊!谢谢
回复 支持 反对

使用道具 举报

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

本版积分规则

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