像 “真正的” 编程语言一样,Bash 也有函数,尽管实现上有些限制。 函数是一个子程序,一个 代码块,实现一组操作,一个执行特定任务的 “黑盒子”。 只要有重复的代码,当一个任务以程序上的细微变化重复时,那么就考虑使用函数。
function function_name {
command...
}
function_name () {
command...
}
第二种形式会让 C 程序员感到高兴(并且更具 可移植性)。
就像在 C 中一样,函数的开括号可以选择出现在第二行。
function_name ()
{
command...
}
![]() | 函数可以 “压缩” 成单行。
在这种情况下,但是,分号 必须跟在函数中最后一个命令之后。
|
函数通过简单地调用其名称来调用、触发。 函数调用等同于一个命令。
示例 24-1. 简单函数
#!/bin/bash
# ex59.sh: Exercising functions (simple).
JUST_A_SECOND=1
funky ()
{ # This is about as simple as functions get.
echo "This is a funky function."
echo "Now exiting funky function."
} # Function declaration must precede call.
fun ()
{ # A somewhat more complex function.
i=0
REPEATS=30
echo
echo "And now the fun really begins."
echo
sleep $JUST_A_SECOND # Hey, wait a second!
while [ $i -lt $REPEATS ]
do
echo "----------FUNCTIONS---------->"
echo "<------------ARE-------------"
echo "<------------FUN------------>"
echo
let "i+=1"
done
}
# Now, call the functions.
funky
fun
exit $? |
函数定义必须先于对它的第一次调用。 没有像 C 中那样的 “声明” 函数的方法。
f1
# Will give an error message, since function "f1" not yet defined.
declare -f f1 # This doesn't help either.
f1 # Still an error message.
# However...
f1 ()
{
echo "Calling function \"f2\" from within function \"f1\"."
f2
}
f2 ()
{
echo "Function \"f2\"."
}
f1 # Function "f2" is not actually called until this point,
#+ although it is referenced before its definition.
# This is permissible.
# Thanks, S.C. |
![]() |
|
甚至可以将一个函数嵌套在另一个函数中,尽管这不是很实用。
f1 ()
{
f2 () # nested
{
echo "Function \"f2\", inside \"f1\"."
}
}
f2 # Gives an error message.
# Even a preceding "declare -f f2" wouldn't help.
echo
f1 # Does nothing, since calling "f1" does not automatically call "f2".
f2 # Now, it's all right to call "f2",
#+ since its definition has been made visible by calling "f1".
# Thanks, S.C. |
函数声明可以出现在不太可能的地方,甚至在通常会放置命令的地方。
ls -l | foo() { echo "foo"; } # Permissible, but useless.
if [ "$USER" = bozo ]
then
bozo_greet () # Function definition embedded in an if/then construct.
{
echo "Hello, Bozo."
}
fi
bozo_greet # Works only for Bozo, and other users get an error.
# Something like this might be useful in some contexts.
NO_EXIT=1 # Will enable function definition below.
[[ $NO_EXIT -eq 1 ]] && exit() { true; } # Function definition in an "and-list".
# If $NO_EXIT is 1, declares "exit ()".
# This disables the "exit" builtin by aliasing it to "true".
exit # Invokes "exit ()" function, not "exit" builtin.
# Or, similarly:
filename=file1
[ -f "$filename" ] &&
foo () { rm -f "$filename"; echo "File "$filename" deleted."; } ||
foo () { echo "File "$filename" not found."; touch bar; }
foo
# Thanks, S.C. and Christopher Head |
_(){ for i in {1..10}; do echo -n "$FUNCNAME"; done; echo; }
# ^^^ No space between function name and parentheses.
# This doesn't always work. Why not?
# Now, let's invoke the function.
_ # __________
# ^^^^^^^^^^ 10 underscores (10 x function name)!
# A "naked" underscore is an acceptable function name.
# In fact, a colon is likewise an acceptable function name.
:(){ echo ":"; }; :
# Of what use is this?
# It's a devious way to obfuscate the code in a script. |
![]() | 当脚本中出现同一函数的不同版本时会发生什么?
|