<imghch AT gmail DOT com>
虽然你可以通过上面的测试和&&、||控制操作符来完成一个大量的程序设计,不过Bash环境中还包含了更亲切的“if-then-else”和 case 语法结构。当你学会了这两种结构之后,你还会学到循环结构,这时你的知识结构才会真正拓展开来。
Bash环境下的if命令是一个复合的命令,它用来测试test语句或者是命令($?)的返回值,根据其真(0)或者假(非0)来执行不同的分支。虽然上面提到的test返回值非0即1,但命令还可能会返回其它的值。关于这点更多内容请到 LPI exam 102 prep: Shells, scripting, programming, and compiling 。
Bash环境下的if命令带一个then子句,这条子句包含一个命令序列,当测试或者是命令的返回值为0时执行。一个或多个可选的子句是elif,每条elif都会附带一个test测试和一条关联一组命令的then子句。最后else和一组命令也是可选的,当if语句中的测试或者是elif语句中的测试都不为真时会执行这组命令,在 if-then-else 结构的结尾用fi标示结束。
现在来使用一下刚刚学到的吧,你可以创建一个简单的计算器来计算一下算术表达式,Example 3.9, “用 if-then-else 来计算表达式”.
Example 3.9. 用 if-then-else 来计算表达式
[user@domain ~]$ 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
> }
[user@domain ~]$ mycalc 3 + 4
3 + 4 = 7
[user@domain ~]$ mycalc 3 + 4**3
3 + 4**3 = 67
[user@domain ~]$ mycalc 3 + (4**3 /2)
-<application>Bash</application>: syntax error near unexpected token `('
[user@domain ~]$ mycalc 3 + "(4**3 /2)"
3 + (4**3 /2) = 35
[user@domain ~]$ mycalc xyz
xyz = 0 or is not an arithmetic expression
[user@domain ~]$ mycalc xyz + 3 + "(4**3 /2)" + abc
xyz + 3 + (4**3 /2) + abc = 35
这个计算器用local那句声明了一个本地变量x,它只在mycalc函数的范围内有效。let函数可以有多个选项,像declare函数一样,选项与函数的作用也是密切相关联。更多信息请查看Bash的 man 手册,或者通过help let获得。
在Example 3.9, “用 if-then-else 来计算表达式”中看到的,你需要确认如果你的表达式用到了 shell 的元字符像( 、 ) 、 * 、 >和<,它们应该被正确地转义。虽然如此,你有了这个按照 shell 的方式来计算算术的相当方便小巧的计算器。
你可能已经注意到了Example 3.9, “用 if-then-else 来计算表达式”中的else子句以及最后两个例子。正如你看到的,给计算器传递xyz它并不会产生错误,但是xyz会被计算成 0 。这个函数并没有那么智能能指出最后的那个例子中用了字符值,并提醒用户。你可以用一个字符串的匹配测试[[ ! ("$*" == *[a-zA-Z]* ]](或者根据你自己设置适当的形式)来排除表达式中包含拼音字母的情况。但是这会阻止十六进制表示法的使用,因为你使用了0x0f来表达十六进制形式的 15 。实际上,shell 环境是允许基数最大到 64 (用base#value表示),这样你可以合理地使用任意拼音字母,包括 _ 和 @ 作为你的输入。用 0 打头的八进制和用 0x 或 0X 打头的十六进制最常用的进制表达法。Example 3.10, “不同基数的运算”列举了一些例子。
Example 3.10. 不同基数的运算
[user@domain ~]$ mycalc 015 015 = 13 [user@domain ~]$ mycalc 0xff 0xff = 255 [user@domain ~]$ mycalc 29#37 29#37 = 94 [user@domain ~]$ mycalc 64#1az 64#1az = 4771 [user@domain ~]$ mycalc 64#1azA 64#1azA = 305380 [user@domain ~]$ mycalc 64#1azA_@ 64#1azA_@ = 1250840574 [user@domain ~]$ mycalc 64#1az*64**3 + 64#A_@ 64#1az*64**3 + 64#A_@ = 1250840574
这些附加的输入已经走出了这篇文章的范围,用你的这个计算器时请谨慎使用。
elif语句非常方便,它帮助你在写脚本时简单地实现的缩进。当你看到Example 3.11, “打印 mycalc”中通过type命令查看mycalc函数的内容时你可能会惊讶。
Example 3.11. 打印 mycalc
[user@domain ~]$ type mycalc
mycalc is a function
mycalc ()
{
local x;
if [ $# -lt 1 ]; then
echo "This function evaluates arithmetic for you if you give it some";
else
if (( $* )); then
let x="$*";
echo "$* = $x";
else
echo "$* = 0 or is not an arithmetic expression";
fi;
fi
}
当然,你可以像Example 3.12, “直接在 shell 环境中通过(( ))和echo命令运算”中一样通过$(( expression ))和echo命令仅仅利用 shell 做算术。那种方式你不会学会任何与函数有关的东西,但提示你的是,在(( expression ))或者是[[ expression ]]中, shell 不会翻译元字符,像 * 等等。