与"真正的"编程语言一样, Bash也有函数, 虽然在某些实现方面稍有限制. 一个函数就是一个子程序, 用于实现一系列操作的代码块, 它是完成特定任务的"黑盒子". 当存在重复代码的时候, 或者当一个任务只需要轻微修改就被重复使用的时候, 你就需要考虑使用函数了.
function function_name {
command...
}
function_name () {
command...
}
C程序员肯定会更加喜欢第二中格式的写法(并且这种写法可移植性更好).
在C中, 函数的左大括号也可以写在下一行中.
function_name ()
{
command...
}
只需要简单的调用函数名, 函数就会被调用或触发.
例子 23-1. 简单函数
1 #!/bin/bash 2 3 JUST_A_SECOND=1 4 5 funky () 6 { # 这是一个最简单的函数. 7 echo "This is a funky function." 8 echo "Now exiting funky function." 9 } # 函数必须在调用前声明. 10 11 12 fun () 13 { # 一个稍微复杂一些的函数. 14 i=0 15 REPEATS=30 16 17 echo 18 echo "And now the fun really begins." 19 echo 20 21 sleep $JUST_A_SECOND # 嘿, 暂停一秒! 22 while [ $i -lt $REPEATS ] 23 do 24 echo "----------FUNCTIONS---------->" 25 echo "<------------ARE-------------" 26 echo "<------------FUN------------>" 27 echo 28 let "i+=1" 29 done 30 } 31 32 # 现在, 调用这两个函数. 33 34 funky 35 fun 36 37 exit 0 |
函数定义必须在第一次调用函数之前完成. 没有像C中函数"声明"的方法.
1 f1 2 # 因为函数"f1"还没有被定义, 这会产生一个错误. 3 4 declare -f f1 # 这样也没用. 5 f1 # 仍然会引起错误. 6 7 # 然而... 8 9 10 f1 () 11 { 12 echo "Calling function \"f2\" from within function \"f1\"." 13 f2 14 } 15 16 f2 () 17 { 18 echo "Function \"f2\"." 19 } 20 21 f1 # 虽然在f2在定义前被引用过, 22 #+ 实际上f2到这儿才被调用. 23 # 所以这么做是正常的. 24 25 # 感谢, S.C. |
甚至可以在一个函数内嵌套另一个函数, 虽然这么做并没有多大用处.
1 f1 () 2 { 3 4 f2 () # nested 5 { 6 echo "Function \"f2\", inside \"f1\"." 7 } 8 9 } 10 11 f2 # 产生一个错误. 12 # 即使你先写出"declare -f f2"也没用. 13 14 echo 15 16 f1 # 什么事都没干, 因为调用"f1"并不会自动调用"f2". 17 f2 # 现在, 可以正确的调用"f2"了, 18 #+ 因为之前调用"f1"使"f2"在脚本中变得可见了. 19 20 # 感谢, S.C. |
函数声明可以出现在看上去不可能出现的地方, 比如说本应出现命令的地方, 也可以出现函数声明.
1 ls -l | foo() { echo "foo"; } # 可以这么做, 但没什么用. 2 3 4 5 if [ "$USER" = bozo ] 6 then 7 bozo_greet () # 在if/then结构中定义了函数. 8 { 9 echo "Hello, Bozo." 10 } 11 fi 12 13 bozo_greet # 只能由Bozo运行, 其他用户使用的话, 会引起错误. 14 15 16 17 # 在某些上下文中, 这样做可能会有用. 18 NO_EXIT=1 # 将会打开下面的函数定义. 19 20 [[ $NO_EXIT -eq 1 ]] && exit() { true; } # 在"与列表"中定义函数. 21 # 如果$NO_EXIT为1, 那就声明"exit ()". 22 # 把"exit"化名为"true", 将会禁用内建的"exit"命令. 23 24 exit # 这里调用的是"exit ()"函数, 而不是"exit"内建命令. 25 26 # 感谢, S.C. |