为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

shell程序编写

2011-06-07 36页 pdf 829KB 45阅读

用户头像

is_850168

暂无简介

举报
shell程序编写 Unix/Linux/Oracle 高级群 8763933 1 shell程序编写 1.1 *Shell是什么? 任何发明都具有供用户使用的界面。UNIX 供用户使用的界面就是 Shell(DOS 的 command 熟悉吧,但 UNIX 的要强大的多)。 Shell 为用户提供了输入命令和参数并可得到 命令执行结果的环境。 为了不同的需要,UNIX 提供了不同的 Shell。现在的 UNIX 大部分都支持 BourneShell, 以下教程就以 BourneShell(Bsh)为例,一步步的领...
shell程序编写
Unix/Linux/Oracle 高级群 8763933 1 shell程序编写 1.1 *Shell是什么? 任何发明都具有供用户使用的界面。UNIX 供用户使用的界面就是 Shell(DOS 的 command 熟悉吧,但 UNIX 的要强大的多)。 Shell 为用户提供了输入命令和参数并可得到 命令执行结果的环境。 为了不同的需要,UNIX 提供了不同的 Shell。现在的 UNIX 大部分都支持 BourneShell, 以下教程就以 BourneShell(Bsh)为例,一步步的领略 UNIX Shell 的强大功能,占先其强大魅 力,达到更方便灵活的管理、应用 UNIX 的目的。 1.1.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 Unix/Linux/Oracle 高级群 8763933 该命令将会列出用户正在执行的进程,即 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-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 环境的不同而不同。 "通配符":* 匹配任何位置 ? 匹配单个字符 Unix/Linux/Oracle 高级群 8763933 [] 匹配的字符范围或列 例如: $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 要为用户创建一个工作的环境,如下: Unix/Linux/Oracle 高级群 8763933 1>当 login 程序激活用户 shell 后,将为用户建立环境变量。从/etc/profile 和.profile 文件 中读出,在这些文件中一般都用$TERM 变量设置终端类型,用$PATH 变量设置 Shell 寻找 可执行文件的路径。 2>从/etc/passwd 文件或命令行启动 shell 时,用户可以给 shell 程序指定一些参数,例如 "-x",可以在命令执行前显示该命令及其参数。后面详细介绍这些参数。 "shell 编程" :本文主要介绍的内容。 shell 本身也是一种语言(*可以先理解为 unix 命令的组合,加上类 C 的条件,循环等程 序控制语句,类似 dos 批处理,但要强大的多),用户可以 通过 shell 编程(脚本,文本文件),完 成特定的工作。 1.2 SHELL变量 下面我们详细的介绍 Bourne Shell 的编程: 自从贝尔实验室设计了 Bourne Shell。从那时起许多厂商根据不同的硬件平台设计了许 多版本得 unix。但在众多版本的 unix 中,Bourne Shell 一直保持一致。 1.2.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 Unix/Linux/Oracle 高级群 8763933 -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 使用终端类型 1.2.2 Bsh里特殊字符及其含义 在 Bsh 中有一组非字母字符。这些字符的用途分为四类:作为特殊变量名、产生文件名、 数据或程序控制以及引用和逃逸字符控制。他们 可以让用户在 Shell 中使用最少的代码完 成复杂的任务。 *> Shell 变量名使用的特殊字符 $# 传送给命令 Shell 的参数序号 $- 在 Shell 启动或使用 set 命令时提供选项 $? 上一条命令执行后返回的值 $$ 当前 shell 的进程号 $! 上一个子进程的进程号 $@ 所有的参数,每个都用双括号括起 $* 所有参数,用双括号括起 $n 位置参数值,n 表示位置 Unix/Linux/Oracle 高级群 8763933 $0 当前 shell 名 *>产生文件名的特殊字符 包括"*","?","[]",上面讲过,不再多说。 *>数据或程序控制使用的特殊字符 >(file) 输出重定向到文件中(没有文件则创建,有则覆盖) >>(file) 输出重定向到文件中(没有则创建,有则追加到文件尾部) <(file) 输入重定向到文件 ; 命令分割符 | 管道符 & 后台运行(例如:sleep 10 &) ` ` 命令替换,重定向一条命令的输出作为另一命令的参数 *>对于引用或逃逸的特殊字符 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: 1.2.3 Bsh的变量 前面我们在多个地方引用了变量,当 Shell 遇到一个"$"符时(没有被引用或逃逸),它将认 为其后为一变量。不论该变量是环境变量还是用户自定义的变量,在命令行中变量名要被变 量值替换。例如命令:ls $HOME 将列出变量 HOME 对应目录下的文件。 用户可以在命令行 中的任何地方进行变量替换。包括命令名本身,例如: $dir=ls $$dir f* 将列出以 f 开头的文件。 现在详细的介绍下 Bsh 的变量。Bsh 中有四类变量:用户定义的变量、位置变量(shell 参 数)、预定义变量及环境变量。 用户定义的变量: 用户定义的变量由字母和下划线组成,并且变量名的第一个字符不能为数字(0~9)。与 Unix/Linux/Oracle 高级群 8763933 其他 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 Unix/Linux/Oracle 高级群 8763933 可以看出,变量替换时将使用命令行中定义的默认值,但变量的值并没有因此而改变。 另外一种替换的方法是不但使用默认值进行替换,而且将默认值赋给该变量。其形式如下: ${variable:=value} 该形式在变量替换后同时把值 value 符给变量 variable。 $echo Hello $UNAME 结果显示:Hello $echo Hello ${UNAME:=there} 结果显示: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 Unix/Linux/Oracle 高级群 8763933 $UNAME=Stephanie $echo $ {UNAME:?"UNAME HAS NOT BEEN SET"} 结果显示:Stephanie 当没有指定 message 时,shell 将显示一条默认的消息,例如: $UNAME= $echo $ {UNAME:?} 结果显示:sh:UNAME:parameter null or not set 1.2.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 中给一个 Unix/Linux/Oracle 高级群 8763933 变量永久赋值。详见" Shell"。 1.3 基本语句 从本节起,我们将详细介绍 Shell 程序设计的基本知识,通过编写 Shell 脚本,用户可 以根据自己的需要有条件的或者重复的执行命令。通过 Shell 程序,可以把单个的 UNIX 命 令组合成一个完全实用的工具,完成用户的任务。 1.3.1 什么是Shell程序 当用户在 UNIX Shell 中输入了一条复杂的命令,如: $ls -R /|greo myname |pg 我们可以称用户在对 Shell 编程,当把这条语句写在一个文件里,并且符给该文件可执 行权限,那么该文件就是我们传统上说的 Shell 程序。 1.3.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 中读取命令。 Unix/Linux/Oracle 高级群 8763933 执行 ba.sh 中命令的另一方法是给文件 ba.sh 执行权限: $chmod +x ba.sh 此时,用户可以输入文件名 ba.sh 做为一个命令来备份自己的数据,需要注意的是,用 这种方法执行命令的时候,文件 ba.sh 必须存在于环境变量$PATH 所指定的路径上。 1.3.3 在Shell中使用数据变量 用户可以在 Shell 中使用数据变量,例如 ba.sh 程序: cd/usr/icewalk ls|cpio -o > /dev/fd0 该程序中要备份的目录为一常量,即该程序只能用来备份一个目录。若在该程序中使用 变量,则会使其更通用: workdir=$1 cd $workdir ls * |cpio -o > /dev/fd0 通过这一改变,用户可以使用程序备份变量$workdir 指定的目录。例如我们要备份 /home/www 的内容,只要运行 ba.sh /home/www 即可实现。(若不明白 $1,下面将详细介绍 shell 参数的传递,$1 代表本 sh 程序-ba.sh 的第一个参数) 1.3.4 在Shell程序中加上注释 为了增加程序的可读性,我们提倡加入注释。在 Shell 程序中注释将以"#"号开始。当 Shell 解释到"#"时,会认为从"#"号起一直到该行行尾为注释。 1.3.5 对Shell变量进行算术运算 高级语言中变量是具有类型的,即变量将被限制为某一数据类型,如整数或字符类型。 Shell 变量通常按字符进行存储,为了对 Shell 变量进行算术运算,必须使用 expr 命令。 expr 命令将把一个算术表达式作为参数,通常形式如下: expr [数字] [操作符] [数字] Unix/Linux/Oracle 高级群 8763933 由于 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 1.3.6 向Shell程序传递参数 一个程序可以使用两种方法获得输入数据。一是执行时使用参数。另一种方法是交互式 地获得数据。vi 编辑程序可以通过交互式的方法获得数据,而 ls 和 expr 则从参数中取得数 据。以上两种方法 Shell 程序都可以使用。在"交互式读入数据"一节中将介绍 Shell 程序通过 交互式的方法获得参数。 通过命令行给 Shell 程序传递参数可以扩大程序的用途。以前面提到的 ba.sh 程序为例: Unix/Linux/Oracle 高级群 8763933 $cat >re.sh cd $workdir cpio -i < /dev/fd0 ^d 程序 re.sh 恢复了 ba.sh 程序备份的所有文件。若只从软盘上恢复一个指定的文件,可以 用该文件名作为参数,传递给 Shell 程序 re.sh: 程序改写如下: $cat >re2.sh cd $workdir cpio -i $1 < /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.4 条件判断语句 条件判断语句是程序设计语言中十分重要的语句,该语句的含义是当某一条件满足时, 执行指定的一组命令。 1.4.1 if - then语句 格式: if command1 Unix/Linux/Oracle 高级群 8763933 then command2 command3 fi ---(if 语句结束) command4 每个程序或命令执行结束后都有一个返回的状态,用户可以用 Shell 变量$?获得这一状 态。if 语句检查前面命令执行的返回状态,若该命令成功执行,那么在 then 和 fi 之间的命 令都将被执行。在上面的命令序列中,command1 和 command4 总要执行。若 command1 成 功执行,command2 和 command3 也将执行。 请看下面程序: #unload -program to backup and remove files cd $1 ls -a | cpio -o > /dev/mnt0 rm * 该程序在备份资料后,删除档案,但当 cpio 命令不能成功执行时,rm 命令还是把资料 删除了,我们可不希望这样,为了避免此情况,可以用 if - then 语句: #--卸载和判断删除程序 cd $1 if ls -a | cpio > /dev/mnt0 then rm * fi 上面程序在 cpio 执行成功后才删除档案 同时,若执行没有成功,我们希望得到提示,sh 中的 echo 命令可以向用户显示消息,并显 示后换行,上面程序可以写成: #--卸载和判断删除程序 cd $1 if ls -a | cpio > /dev/mnt0 then echo "正删除文件资料... ..." rm * fi echo 命令可以使用一些特殊的逃逸字符进行格式化输出,下面是这些字符及其含义: \b Backspace \c 显示后不换行 \f 在终端上屏幕的开始处显示 \n 换行 Unix/Linux/Oracle 高级群 8763933 \r 回车 \t 制表符 \v 垂直制表符 \ 反斜框 \0nnn 用 1,2 或 3 位 8 进制整数表示一个 ASCII 码字符 1.4.2 if - then - else语句 不用多说它的作用,别的高级语言中都有,格式为: if command1 then command2 command3 else command4 command5 fi 在此结构中,command1 中是先执行,当 command1 成功执行时,将执行 command2 和 command3,否则执行 command4 和 command5 注意看下面程序: #备份程序 cd $1 if ls -a |cpio -o > /dev/mnt0 then echo "删除源资料... ..." rm * else echo "磁带备份失败!" fi 1.4.3 test命令进行条件测试 if 语句可以通过测试命令执行的返回状态来控制命令的执行,若要测试其他条件,在 bsh 中可以使用 test 命令。该命令检测某一条件,当条件为真时返回 0,否则返回非 0 值。 test 命令可以使 Shell 程序中的 if 语句象其他程序语言中的条件判断语句一样,具有很强的 功能。 test 命令的使用方法为: test condition Unix/Linux/Oracle 高级群 8763933 可测试的条件分为 4 类: 1)测试两个字符串之间的关系。 2)测试两个整数之间关系。 3)测试文件是否存在或是否具有某种状态或属性。 4)测试多个条件的与(and)或(or)组合。 1.4.4 条件语句>>test语句 1.4.4.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 操作符测试一个串结果是一样的,例如: Unix/Linux/Oracle 高级群 8763933 $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 命令,所以显示参数错。 1.4.4.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 Unix/Linux/Oracle 高级群 8763933 $echo $? 结果显示:1 $test $str1 -eq $str2 $echo $? 结果显示:0 1.4.4.3 有关文件的测试 使用 test 进行的第三类测试是测试文件的状态,用户可以测试文件是否存在,是否可写 以及其他文件属性。下面是文件测试时使用的选项。注意只有文件存在时,才有可能为真。 -r file 用户可读为真 -w file 用户可写为真 -x file 用户可执行为真 -f file 文件为正规文件为真 -d file 文件为目录为真 -c file 文件为字符特殊文件为真 -b file 文件为块特殊文件为真 -s file 文件大小非 0 时为真 -t file 当文件描述符(默认为 1)指定的设备为终端时为真 1.4.4.4 复杂的条件测试(and 、or 、not) -a 与 -o 或 ! 非 就是组合条件了,任何高级语言中都有的(NOT 、AND 、OR),例如: $test -r em.null -a -s em.null $echo $? 结果显示:1 说明了 em.null 并不是可读并且非空的文件 1.4.4.5 另一种执行test的方法 bsh 中还有另一种执行 test 命令的方法,就是把测试条件放到一对[ ]中,例如: $int1=4 $[ $int1 -gt 2 ] $echo $? 结果显示:0 要注意在[ 的后面和 ]符号的前面要有一个空格。 Unix/Linux/Oracle 高级群 8763933 下面我们用 test 命令写个简单但比较完善的程序: #-- 备份程序 #-- 检查参数 if [ $# -ne 1 ] then echo "请在程序名后面指出要备份文件所在目录!" exit 1 fi #-- 检查目录名是否有效 if [ !-d "$1" ] then echo "$1 不是一个目录!" exit 2 fi cd $1 ls -a | cpio -o >/dev/mnt0 if [ $? -eq 0 ] then rm * else echo "cpio 执行不成功!备份失败..." exit 3 fi 1.4.4.6 空命令 在 Bsh 中用 : 代表空命令,就是充个数,什么都不做 1.4.4.7 嵌套if语句和elif结构 检查条件 1 A:当条件 1 为真,则执行一部分操作 B:若条件 1 为假,检查条件 2 1)若条件 2 为真,执行另外一部分操作 2)若条件 2 为假,检查条件 3 3)若条件 3 为真,执行其他一部分操作 语法如下: if command Unix/Linux/Oracle 高级群 8763933 then command else if command then command else if command then command fi fi fi 1.4.4.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 语句完成相同的功能,用户可以根据自己的喜好选择一种 使用。 1.4.4.9 case语句 前面说的 elif 语句替代 if-then-else 语句,但有时在编程时还会遇到对同一变量进行多次 的测试,该情况可以用多个 elif 语句实现,但还有一种更简单的方法就是用 case 语句。 case 语句不但取代了多个 elif 和 then 语句,还可以用变量值对多个模式进行匹配,当某 Unix/Linux/Oracle 高级群 8763933 个模式与变量值匹配后,其后的一系列命令将被执行,下面是 case 语句使用的语句。 case value in pattem 1) command command;; pattem 2) command command;; .... pattem) command; esac case 语句只执行其中的一组命令,当变量值与多个模式相匹配时,只有第一个匹配的模 式对应的命令被执行。";;"表示该模式对应的命令部分程序。 通过学习下面的 read 语句,我们们再举例子说明 case 语句的用法。 1.4.4.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 Unix/Linux/Oracle 高级群 8763933 下面用个 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
/
本文档为【shell程序编写】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索