个人工具
登录
查看“Shell编程基础”的源代码 - Ubuntu中文
页面
讨论
查看源代码
历史
搜索
导航
首页
最近更改
随机页面
页面分类
帮助
编辑
编辑指南
沙盒
新闻动态
字词处理
工具
链入页面
相关更改
特殊页面
页面信息
查看“Shell编程基础”的源代码
来自Ubuntu中文
←
Shell编程基础
跳转至:
导航
,
搜索
因为以下原因,你没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
== Shell里的流程控制 == === if 语句 === if 表达式如果条件命令组为真,则执行 then 后的部分。标准形式: <source lang=bash>if 判断命令,可以有很多个,真假取最后的返回值 then 如果前述为真做什么 [ # 方括号代表可选,别真打进去了! elif 可以再来个判断,如果签名为假继续尝试这里 then 如果前述为真做什么 ] else 如果全都不行做什么 fi # 结束,就是倒写的 if 啦。</source> 现实生活中一般判断只有一个命令,所以你看到的一般是: <source lang=bash>if ....; then # 你也可以写成 if 之后换行,这样就不用分号了。 .... fi</source> 大多数情况下,可以使用测试命令来对条件进行测试,比如可以比较字符串、判断文件是否存在及是否可读等等……在 bash 中一般采用更好用的 <tt>[[ ... ]]</tt> 语法进行条件测试,而通用方法是 <tt>[ ... ]<tt>(相当于 <tt>test ...</tt>)。两者都接纳的常用测试语句有: ;<tt>-f "filename"</tt>:判断是否是一个文件 ;<tt>-x "/bin/ls"</tt>:判断/bin/ls是否存在并有可执行权限 ;<tt>-n "$var"</tt>:判断 $var 变量是否有值 ;<tt>"$a" == "$b"</tt>:判断$a和$b是否相等 前者可以使用 <tt>help [[</tt> 查询用法,后者使用 <tt>help [</tt> (bash) 或 <tt>man test</tt> 查询。下面的语句用到了这个内容: <source lang=bash>if [ "${SHELL}" == "/bin/bash" ]; then echo "your login shell is the bash (bourne again shell)" else echo "your login shell is not bash but ${SHELL}" fi</source> 变量 <tt>$SHELL</tt> 包含有登录shell的名称,我们拿它和 <tt>/bin/bash</tt> 进行比较以判断当前使用的shell是否为bash。你可能会问了,要是 bash 路径不是这个呢? === && 和 || 操作符 === 熟悉C语言的朋友可能会喜欢下面的表达式: <source lang=bash>[ -f "/etc/shadow" ] && echo "This computer uses shadow passwords"</source> 这里的 && 就是一个快捷操作符,如果左边的表达式为真(返回 0——“成功”)则执行右边的语句,你也可以把它看作逻辑运算里的与操作。上述脚本表示如果/etc/shadow文件存在,则打印“This computer uses shadow passwords”。 同样shell编程中还可以用或操作 (||),例如: <source lang=bash>#!/bin/bash mailfolder=/var/spool/mail/james [ -r "$mailfolder" ] || { echo "Can not read $mailfolder"; exit 1; } echo "$mailfolder has mail from:" grep "^From " $mailfolder</source> 该脚本首先判断mailfolder是否可读,如果可读则打印该文件中以"From"开头的行。如果不可读则或操作生效,打印错误信息后脚本退出。需要注意的是,这里我们必须使用如下两个命令: <source lang=bash>{ echo "Can not read $mailfolder"; # 打印错误信息 exit 1; # 退出程序 }</source> 我们使用花括号以组合命令的形式将两个命令放到一起作为一个命令使用。即使不用与和或操作符,我们也可以用if表达式完成任何事情,但是使用与或操作符会更便利很多。 要注意 Shell 中的 && || 程序流操作符不表现任何优先级区别,完全是先看到谁就先处理谁的关系。 === case 语句 === case表达式可以用来匹配一个给定的字符串,而不是数字(可别和C语言里的switch...case混淆)。 <source lang="bash"> case ... in ...) do something here ;; esac </source> file命令可以辨别出一个给定文件的文件类型,如:file lf.gz,其输出结果为: <source lang="bash"> lf.gz: gzip compressed data, deflated, original filename, last modified: Mon Aug 27 23:09:18 2001, os: Unix </source> 我们利用这点写了一个名为smartzip的脚本,该脚本可以自动解压bzip2, gzip和zip 类型的压缩文件: <source lang="bash"> #!/bin/bash ftype="$(file "$1")" case "$ftype" in "$1: Zip archive"*) unzip "$1" ;; "$1: gzip compressed"*) gunzip "$1" ;; "$1: bzip2 compressed"*) bunzip2 "$1" ;; *) echo "File $1 can not be uncompressed with smartzip";; esac </source> 你可能注意到上面使用了一个特殊变量 {{code|$1}},该变量包含有传递给该脚本的第一个参数值。也就是说,当我们运行: <source lang="bash"> smartzip articles.zip </source> {{code|$1}} 就是字符串 articles.zip。 === select 循环语句 === select 循环语句是bash的一种扩展应用,擅长于交互式场合。 用户可以从一组不同的值中进行选择: <source lang="bash"> pocket=() select var in 跳跳糖 糖 很多糖 企鹅糖; do echo "除了 $var 还要什么吗?" if ((RANDOM%4 == 0)); then echo "呀!时间不够了,快上车!" break # break 还是那个 break fi pocket+=("$var") done echo "你最后说的那个 $var 弄丢了……" IFS='、' echo "现在口袋里只有:${pocket[*]}。" IFS=$' \t\n' </source> 下面是一个简单的示例: <source lang="bash"> #!/bin/bash echo "What is your favourite OS?" select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do break; done echo "You have selected $var" </source> 该脚本的运行结果如下: <source lang="bash"> What is your favourite OS? 1) Linux 2) Gnu Hurd 3) Free BSD 4) Other #? 1 You have selected Linux </source> === while/for 循环=== 在shell中,可以使用如下循环: <source lang="bash"> while ...; do .... done </source> 只要测试表达式条件为真,则while循环将一直运行。关键字"break"用来跳出循环,而关键字”continue”则可以跳过一个循环的余下部分,直接跳到下一次循环中。 for循环会查看一个字符串列表(字符串用空格分隔),并将其赋给一个变量: <source lang="bash"> for var in ....; do .... done </source> 下面的示例会把A B C分别打印到屏幕上: <source lang="bash"> #!/bin/bash for var in A B C ; do echo "var is $var" done </source> 下面是一个实用的脚本showrpm,其功能是打印一些RPM包的统计信息: <source lang="bash"> #!/bin/bash # list a content summary of a number of RPM packages # USAGE: showrpm rpmfile1 rpmfile2 ... # EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpm for rpmpackage in "$@"; do if [ -r "$rpmpackage" ];then echo "=============== $rpmpackage ==============" rpm -qi -p $rpmpackage else echo "ERROR: cannot read file $rpmpackage" fi done </source> 这里出现了第二个特殊变量$@,该变量包含有输入的所有命令行参数值。如果你运行showrpm openssh.rpm w3m.rpm webgrep.rpm,那么 "$@"(有引号) 就包含有 3 个字符串,即openssh.rpm, w3m.rpm和 webgrep.rpm。$*的意思是差不多的。但是只有一个字串。如果不加引号,带空格的参数会被截断。
返回至
Shell编程基础
。