【Bash百宝箱】shell函数

本文详细介绍了Shell函数的基本格式、定义方式、参数使用、退出状态及如何使用扩展命令等内容。

1、基本格式

shell函数的格式如下:

name () compound-command [redirection]
function name [()] compound-command [redirection]

shell函数实际上就是一个简单的shell命令,在当前shell执行,它代表了一组复合命令compound-command即函数体,函数体一般放在一对花括号中。关键字function可有可无,当使用了关键字function时,函数名name后面的一对圆括号是可选的。shell函数最后的重定向redirection也是可选的。

下面是几种shell函数的不同用法:

test_function()
{
    echo "test_function called"
    pwd
}

function test_function2()
{
    echo "test_function2 called"
    pwd
}

function test_function3
{
    echo "test_function3 called"
    pwd
}

function test_function4()
{
    echo "test_function4 called"
    pwd
} > test_function.save

例子中,函数体都包括两个命令”echo“和“pwd”,test_function没有使用关键字function,test_function2使用了关键字function和圆括号,test_function3使用了关键字function但没有使用圆括号,test_function4将函数的标准输出重定向到了文件test_function.save。执行shell函数就像执行shell命令一样简单,命令名即函数名。

2、函数定义

在shell中,变量名可以和函数名相同,但容易引起混淆,所以变量名和函数名尽量不要相同。

$ foo=bar
$ foo() { echo "foo called"; }
$ echo $foo
bar
$ foo
foo called

同名函数可以多次定义,后面的定义会覆盖前面的定义,取消定义可使用命令“unset -f function_name”。

$ foo() { echo "11111"; }
$ foo() { echo "22222"; }
$ foo
22222
$ unset -f foo
$ foo
未找到 'foo' 命令,您要输入的是否是:
 命令 'fio' 来自于包 'fio' (universe)
 命令 'xoo' 来自于包 'xoo' (universe)
 命令 'fox' 来自于包 'objcryst-fox' (universe)
 命令 'goo' 来自于包 'goo' (universe)
 命令 'fog' 来自于包 'ruby-fog' (universe)
 命令 'zoo' 来自于包 'zoo' (universe)
 命令 'fgo' 来自于包 'fgo' (universe)
 命令 'fop' 来自于包 'fop' (main)
foo:未找到命令

在函数体中,对函数外的全局变量赋值时将改变这个变量的值,如果在函数体内的变量前使用关键字“local”,这个变量将被当作局部变量来使用,不会影响到同名的全局变量。

$ foo=1
$ bar=2
$ foobar() { foo=100; local bar=100; echo $foo $bar; }
$ foobar
100 100
$ echo $foo $bar
100 2

3、函数参数

shell函数的参数为位置参数,也就是说,这些参数都被编了序号,0表示shell脚本名或shell解释器名bash,1表示第一个参数,2表示第二个参数,等等,而参数的个数则保存在了一个特殊的参数“#”,另外特殊参数“*”和“@”也可以对函数参数进行扩展。在shell中访问变量或这些特殊参数使用美元符号“$”,下面举例说明函数参数的用法。

$ foo() { echo $# $0 $1 $2; echo $*; echo $@; }
$ foo a b c d
4 bash a b
a b c d
a b c d

使用关键字“shift”可以对位置参数进行移位,默认向左移动一位,效果如下:

$ foo() { echo $*; shift; echo $*; }
$ foo a b c d
a b c d
b c d

shift也可以带有一个参数,非负数,表示向左移动的位数,有效范围介于0到位置参数的总个数之间。

$ foo() { echo $*; shift 2; echo $*; }
$ foo a b c d
a b c d
c d

shell会对上面提到的几个特殊参数等作特殊处理,下面作详细介绍。

“*”:星号。扩展为从1开始的所有位置参数。如果它出现在双引号中,则扩展为一个包含每个参数的单词,参数之间用特殊变量IFS的第一个字符分隔,IFS即Internal Field Separator。也就是说,"$*""$1c$2c..."是等价的,其中c是特殊变量IFS的第一个字符,如果IFS没有设置,则参数之间用空格分隔,如果IFS为空,则参数直接相连,中间没有分隔。

$ foo() { echo $*; }
$ foo a b c d
a b c d
$ foo() { echo "$*"; }
$ foo a b c d
a b c d
$ IFS=
$ foo() { echo $*; }
$ foo a b c d
a b c d
$ foo() { echo "$*"; }
$ foo a b c d
abcd
$ unset IFS
$ foo() { echo $*; }
$ foo a b c d
a b c d
$ foo() { echo "$*"; }
$ foo a b c d
a b c d
$ IFS=:
$ foo() { echo $*; }
$ foo a b c d
a b c d
$ foo() { echo "$*"; }
$ foo a b c d
a:b:c:d

“@”:扩展为从1开始所有位置参数。如果它出现在双引号中,则每个参数都扩展为一个单词,也就是说,"$@""$1c""$2c"...是等价的,其中c是特殊变量IFS的第一个字符,如果IFS没有设置,则参数之间用空格分隔,如果IFS为空,则参数直接相连,中间没有分隔。

“#”:井号。扩展为位置参数的个数,用十进制表示。

“0”:数字0。扩展为shell或者shell脚本的名称,它是在shell初始化时设置的,如果Bash启动时带有包含命令的的文件名参数,"$0"就被设为该文件名,如果Bash启动时带有“-c”选项,则"$0"被设为待执行字符串后面的第一个参数(如果这个参数存在),否则,它就是用来启动Bash的文件名,即命令行的第一个参数。

“?”:问号。扩展为最近在前台执行的命令的退出状态。

$ uname -p
x86_64
$ echo $?
0
$ uname x
uname: 额外的操作数 "x"
Try 'uname --help' for more information.
$ echo $?
1

“!”:叹号。扩展为最近在后台异步执行的命令的退出状态。

$ echo $!

$ uname -p
x86_64
$ echo $!

$ uname -p &
[1] 20887
$ x86_64

[1]+  已完成               uname -p
$ echo $!
20887

“$”:美元符号。扩展为当前shell的进程号,在子shell中,扩展为启动shell的进程号,而不是子shell的进程号。

$ foo() { echo $$; }
$ foo
20740
$ foo &
[1] 20849
$ 20740

[1]+  已完成               foo
$ echo $$
20740

“-”:连字符。扩展为当前的所有选项,这些选项是启动时给定的,或者通过内部命令set打开的,或者由shell本身打开的。

$ foo() { echo $-; }
$ foo
himBH

”_“:下划线。在shell启动时,设为启动shell的绝对路劲,或者在执行环境或参数列表中所传递的待执行的shell脚本的绝对路径。随后,扩展为前一条命令的最后一个参数扩展后的值。还可设为每个已执行命令的绝对路径,这些路径是启动时指定的并且导入到命令的执行环境中。检查邮件时,这个变量保存邮箱文件的文件名。

$ touch t.sh
$ bash t.sh
$ echo $_
t.sh
$ foo() { echo $_; }
$ foo
t.sh
$ foo
foo

4、退出状态

函数定义本身也是一个shell命令,定义成功时其退出状态为0。在执行shell函数时,如果出现了关键字“return”,函数将提前结束,其退出状态为0;如果return后面是一个有效的数字(0到255),则shell函数的退出状态为这个数字;如果没有return,退出状态为shell函数体内执行的最后一个命令的退出状态。

5、扩展命令

先看如下使用了重定向的shell函数:

$ foo() { echo $*; } > foo.save
$ foo a b c d
$ cat foo.save 
a b c d

上述foo函数把标准输出即函数参数重定向到了文件foo.save,此外,还可以使用shell扩展命令把foo函数的标准输出保存到shell变量中,shell扩展命令的格式为:

$ var=`your_command`
$ var=$(your_command)

例子:

$ foo() { echo $*; }
$ var=`foo a b c d`
$ echo $var
a b c d
$ var2=$(foo a b c d)
$ echo $var2
a b c d
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值