函数
函数是在ATT的UNIX SYSTEM VR2版本开始引入到Bourne shell中的,并在Bourne again shell中得到强化。函数就是一个命令或者一组命令的名字。函数可以使程序模块化并提高效率,可以就在当前shell环境中执行。换言之,在执行像ls这样的可执行程序时并不产生子进程。你甚至可以把函数保存在文件中,而在准备使用时再把它们载入脚本。
在使用函数时需遵循以下原则:
- shell可以决定是执行一个别名,然后是函数,内建命令,最后才执行可执行程序。
- 函数在使用前必须定义。
- 函数在当前环境下运行。它跟调用它的脚本分享变量,并通过位置参量传递参数,通过local函数可以在函数内部建立本地变量。
- 如果你在函数中使用exit命令,则可以退出整个脚本。如果函数退出,就返回到脚本中调用该函数的地方。
- 函数中的return命令返回函数中最后一个命令的退出状态值或者给定的参数值。
- 使用内建命令export -f可以把函数输出给子shell。
- 使用内建命令declare -f可以显示定义的函数清单。如果只显示函数的名字,可以用命令declare -F。
- 像变量一样,函数内部陷阱(trap)是全局的。它们可以被脚本和脚本激活的函数共享。如果是一个陷阱被定义为函数,它就可以被脚本共享。但是它可能产生意想不到的效果。
- 如果函数保存在其他的文件中,就必须通过source或者dot命令把它们装入当前的脚本。
- 函数可以递归。也就是说,函数可以调用自己,而且调用的次数没有限制。
格式
function function_name { commands; commands; } # 书写时函数体与花括号之间必须有空格
示例一
function dir { echo "Directories: "; ls -l | akw '^d' '{print $NF}'; }
function dir () { echo "Directories: "; ls -l | akw '^d' '{print $NF}'; }
# 函数名后面的括号某些情况下可以不加
复位函数:使用命令unset从内存中删除函数
格式
unset -f function_name
输出函数:函数可以输出给子shell
格式
export -f function_name
export -n function_name #取消导出一个函数
函数参数和返回值
因为函数可以在当前shell内执行,变量对于函数和shell来说都是可见的。所以在函数内对于环境变量的任何修改都将影响shell。
内建的local函数: 要创建只在函数内部使用,且当函数退出时就消失的变量,可以用内建的local函数实现。
参数:通过为止参量可以向函数传递参数。位置参量对于函数来说是专用的。也就是说参数将不影响在函数外使用的任何位置参量。
内建的return函数:return函数可以用来退出函数并返回到脚本中调用该函数的地方(记住,它与exit有很大的区别,exit不但退出函数,而且还会直接退出整个脚本)。如果你没有为return命令指定参数,返回的函数值就是最后一行脚本的退出状态值。如果赋值给return命令,则这个值将保存在变量?中,这个值可以是0~256之间的一个整数。因为return命令限制只能返回一个0~256之间的整数。因此你可以使用命令替换来捕捉函数的输出。把整个函数放在括号内,前面是一个$,就是$(function_name)或者就像传统的捕捉linux命令的输出一样,通过引用把输出赋值给一个变量。
示例一
#!/usr/bin/bash
function usage { echo "error: $*" 2>&1; exit 1; }
if (( $# != 2 ))
then
usage "$0: requires two arguments"
fi
if [[ ! ( -r $1 && -w $1 ) ]]
then
usage "$0: not readable and writeable"
fi
echo The arguments are $* # 这里的位置参数与函数内的同名位置函数互不影响,两个完全是相互独立的
exit
示例二
#!/usr/bin/bash
increment () {
local sum
let "sum = $1 + 1"
return $sum
}
echo -n "The sum is "
increment 5
echo $?
echo $sum #空值,因为是函数的local变量在函数退出时就被删除了
示例二
#!/usr/bin/bash
function square {
local sq
let "sq = $1 * $1"
echo "number to be squared is $1."
echo "The result is $sq" # 输出内容作为返回值
}
echo -n "Give me a number to square: "
read number
value_return=$(square $number)
echo "The square value is $value_return."
函数和source(或者dot)命令
保存函数:函数通常被定义在.profile中,所以当你登录时,它们就被定义了。函数可以被输出并保存在文件中。当你需要它们的时候,可以使用source命令或者dot命令和文件名来激活在这些文件中定义的函数。
示例一
#!/usr/bin/bash
#scriptname: first_one
echo "Hello World!"
function go {
echo "I want to go fishing."
}
function fishing {
echo "wow, i got a fish!"
}
#在第一个脚本里面定义两个函数。
#!/usr/bin/bash
#scriptname:second_one
source first_one.sh # 在第二个脚本中导入第一个脚本定义的函数。除了用source,也可以使用.号来加载文件
go
fishing
# Hello world!
# I want to go fishing.
# wow, i got a fish!
# 如果first_one.sh里面不光定义了函数,还执行了其他命令,那么在导入文件的时候,第一个脚本里面的命令也会被一起执行。
source和.操作符的作用其实与我们在修改环境配置文件以后需要重新用source来初始化一下是一样的原理和作用。当我们source .bash_profile的时候,其实就是相当于执行了文件里面的命令,因此一些定义的环境变量会被导出。