定义函数
function fname()
{
statements;
}
或者:
fname()
{
statements;
}
调用函数
不带参数:
$ fname ;
带参数:
$ fname arg1 arg2 ;
读取参数
fname()
{
echo $1, $2; # 输出访问的参数1 和参数2
echo "$@"; # 以列表形式一次打印所有参数
echo "$*"; # 类似于 $@,但是参数被作为单个实体
类似,在脚本里面也可以用同样的方法读取参数。
$0
是脚本名,也就是调用语句的第一个单词$1
是第一个参数$2
是第二个参数$n
是第 n 个参数$@
被扩展成$1
$2
$*
被扩展成$1c$2c$3
其中 c 是环境变量 IFS 的第一个字符$@
要比$*
常用,因为$*
将所有参数当做单个字符串,因此很少用。
读取命令返回值
$ cmd;
$ echo $?;
$?
会给出上一个命令(cmd
)的返回值
返回值被称为退出状态,用于分析命令执行成功与否,如果命令成功退出,那么退出状态为 0 否则为非 0.
可以按照下面的方法检测某个命令是否成功结束:
#!/bin/bash
# Filename: success_test.sh
CMD="$@"
$CMD
if [ $? -eq 0 ];
then
echo "$CMD executed successfully"
else
echo "$CMD terminated unsuccessfully"
fi
递归
Fib()
{
if [ $1 -lt 1 ]; then echo "Fib($1)=0"; return 0;
elif [ $1 -lt 3 ]; then echo "Fib($1)=1"; return 1;
else
local a b ans;
Fib $(( $1 - 1 )); a=$?;
Fib $(( $1 - 2 )); b=$?;
ans=$(( a + b ))
echo "Fib($1)=$ans"
return $ans;
fi
}
注意,这里的所有变量都是全局的,因此需要用 local 关键字进行局部变量的声明;
不过,一般而言返回值不是用于逻辑计算,输出才是,所以像上面这个函数,这样写更为合理:
Fib() {
[ $1 -lt 1 ] && echo 0 || [ $1 -lt 3 ] && echo 1 || echo $(( $(Fib $(( $1 - 1))) + $(Fib $(( $1 - 2))) ))
}
$ Fib 2
1
$ Fib 15
610
上面这个才是斐波那契数列的笨拙递归解,下面再来写一个最大公约数:
Gcd() {
[ $2 -eq 0 ] && echo $1 || Gcd $2 $(( $1 % $2 ))
}
$ Gcd 3 5
1
$ Gcd 12 16
4
$ Gcd 352 624
16
fork 炸弹
:(){ :|:& };:
http://en.wikipedia.org/wiki/Fork_bomb
导出函数
函数能够像环境变量一样用 export 导出,这样可以让函数的作用与扩展到子进程。
export -f name
向命令传递参数
例如我们一般调用命令的参数,有些是仅仅是可用选项,有些是带有的参数,可能会有如下方式:
command -p -v -k 1 file
command -pv -k 1 file
command -vpk 1 file
command file -pvk 1
上面的调用方式是等价的,但是如何在 command 中获取参数值,本书没有提及。
这个议题本书一笔带过,参考另文:https://www.huangwenchao.com.cn/?p=2721&preview=true
【转载请附】愿以此功德,回向 >>
原文链接:http://www.huangwenchao.com.cn/2015/12/bash-shell-9.html【每日一SHELL (9) 函数和参数】