<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 不会翻译元字符,像 * 等等。