Shell脚本

test 和 [

test 内嵌命令会根据对表达式 expr 的计算结果来确定返回 0(True)或 1(False) 。也可以使用方括号,test  expr 和 [ expr ] 是等效的。可以通过显示 $? 来检查返回值.

几个简单的测试例子

        [ian@pinguino ~]$ test 3 -gt 4 && echo True || echo false
false
[ian@pinguino ~]$ [ "abc" != "def" ];echo $?
0
[ian@pinguino ~]$ test -d "$HOME" ;echo $?
0
在第一个例子中, -gt 操作符用来在两个数值之间进行数学比较运算。在第二个例子中, 使用了另外一种 [ ] 形式来比较两个字符串是否相等。在最后一个例子中,使用 -d 一元操作符对 HOME 变量的值进行测试,看它是否是一个目录。

数值可以使用 -eq、-ne、-lt、-le、-gt 或 -ge 进行比较,分别表示等于、不等于、小于、小于或等于、大于、大于或等于。(this is reverse to the syntax in Perl)

字符串可以使用操作符 =、!=、< 和 > 分别进行等于、不等于或第一个字符串是在第二个字符串之前还是之后的比较操作。一元操作符 -z 测试字符串是否为空;如果字符串不为空,那么 -n 或不使用任何操作符就返回 True。

几个文件测试的例子
操作符特性
-d 目录
-e 存在(也可以使用 -a)
-f 普通文件
-h 符号链接(也可以使用 -L)
-p 命名的管道
-r 可以读取
-s 非空
-S Socket
-w 可以写入
-N 上次读取之后已经被修改过了

 

文件对测试
操作符
如果符合该条件就为 True
-nt
测试文件 1 是否比文件 2 更新。修改日期会在这个比较和下个比较中使用。
-ot
测试文件 1 是否比文件 2 更旧。
-ef
测试文件 1 是否是到文件 2 的硬链接。

 

 -o 操作符允许测试不同的 shell 选项,这些选项可通过 set -o  option 进行设置,如果选项已设置就返回 True (0),否则返回 False (1)。

 

最后,-a-o 操作允许分别使用逻辑 AND 和 OR 来合并表达式,而一元操作符 ! 则是对测试含义取反。可以使用圆括号来对表达式进行分组,并覆盖默认的优先级顺序。记住 shell 通常会在一个子 shell 中运行表达式,因此需要使用 "( 和 ") 对圆括号进行转义,或者使用单引号或双引号将这些操作符围起来。

test "a" != "$HOME" -a 3 -ge 4 ; echo $?

 (( )) 复合命令 可以计算一个算术表达式的值,如果这个表达式的值为 0 就将退出状态设置为 1;如果表达式的值不为 0,就将退出状态设置为 0。不需要对 (()) 之间的操作符进行转义。数值计算是按照整型进行的。被除数为 0 会产生错误,但溢出不会产生错误。也可以执行在 C 语言中很常见的数值、逻辑和位操作。let 命令也可以执行一个或多个算术表达式。它通常用来对数值变量进行赋值。

 对算术表达式进行赋值和测试

        [ian@pinguino ~]$ let x=2 y=2**3 z=y*3;echo $? $x $y $z
0 2 8 24
[ian@pinguino ~]$ (( w=(y/x) + ( (~ ++x) & 0x0f ) )); echo $? $x $y $w
0 3 8 16
[ian@pinguino ~]$ (( w=(y/x) + ( (~ ++x) & 0x0f ) )); echo $? $x $y $w
0 4 8 13

 

(( )) 类似, [[ ]] 复合命令让您可以使用更加自然的语法进行文件名和字符串测试。可以使用圆括号和逻辑操作符组合 test 命令所允许的测试。

 使用 [[ 进行组合

        [ian@pinguino ~]$ [[ ( -d "$HOME" ) && ( -w "$HOME" ) ]] &&  
> echo "home is a writable directory"
home is a writable directory

 

 使用 if, then, else 语句计算表达式

        [ian@pinguino ~]$ function mycalc ()
> {
> local x
> if [ $# -lt 1 ]; then
> echo "This function evaluates arithmetic for you if you give it some"
> elif (( $* )); then
> let x="$*"
> echo "$* = $x"
> else
> echo "$* = 0 or is not an arithmetic expression"
> fi
> }
[ian@pinguino ~]$ mycalc 3 + 4
3 + 4 = 7
[ian@pinguino ~]$ mycalc 3 + 4**3
3 + 4**3 = 67
[ian@pinguino ~]$ mycalc 3 + (4**3 /2)
-bash: syntax error near unexpected token `('
[ian@pinguino ~]$ mycalc 3 + "(4**3 /2)"
3 + (4**3 /2) = 35
[ian@pinguino ~]$ mycalc xyz
xyz = 0 or is not an arithmetic expression
[ian@pinguino ~]$ mycalc xyz + 3 + "(4**3 /2)" + abc
xyz + 3 + (4**3 /2) + abc = 35
计算器使用 local 语句将 x 声明为本地变量,它只能在 mycalc 函数内部使用。 let 函数有几个可能的选项,与之密切相关的 declare 函数也是一样。请查看 bash 的手册页或使用 help let 来获得更多信息。

正如在清单 36 中所看到的一样,如果使用了 shell 元字符,例如 (、)、*、> 和 <,就需要仔细确保表达式进行了正确的转义。

 

case 复合命令是以 case WORD in 开始并以 esac ("case" 这个单词倒着拼)结束。每个 case 语句可以包含单个模式或者多个模式(使用 | 分隔开),后面是一个 ) 符号,然后是一个语句列表,最后是两个分号(;;)。

 使用 case 命令

        [ian@pinguino ~]$ type myorder
myorder is a function
myorder ()
{
case "$*" in
"coffee" | "decaf")
echo "Hot coffee coming right up"
;;
"tea")
echo "Hot tea on its way"
;;
"soda")
echo "Your ice-cold soda will be ready in a moment"
;;
*)
echo "Sorry, we don't serve that here"
;;
esac
}
[ian@pinguino ~]$ myorder decaf

Hot coffee coming right up
[ian@pinguino ~]$ myorder tea
Hot tea on its way
[ian@pinguino ~]$ myorder milk
Sorry, we don't serve that here

注意使用 '*' 可以匹配之前尚未匹配的任何内容。

 

命令替换让您可以通过简单地在命令两边加上一个 $( 和 ) 或使用一对反单引号 ` 来将一个命令的输出结果作为另外一个命令的输入使用。如果希望嵌套地使用一个命令的输出结果作为生成最终结果的另外一个命令的一部分,就会发现 $() 格式的优点;它也使得确定要执行什么操作变得更加简单,因为圆括号区分左、右,而两边的反单引号是完全相同的。

 

shell 允许您设置 -x 选项来在 shell 执行函数的同时对命令及其参数进行跟踪.

 

For、while 和 until 循环

        [ian@pinguino ~]$ for x in abd 2 "my stuff"; do echo $x; done
abd
2
my stuff
[ian@pinguino ~]$ for (( x=2; x<5; x++ )); do echo $x; done
2
3
4
[ian@pinguino ~]$ let x=3; while [ $x -ge 0 ] ; do echo $x ;let x--;done
3
2
1
0
[ian@pinguino ~]$ let x=3; until echo -e "x="c"; (( x-- == 0 )) ; do echo $x ; done
x=2
x=1
x=0

 

posted @ 2008-08-19 16:49  xiaoyixy  阅读(401)  评论(0编辑  收藏  举报