-----------
由于Bash的易于编程等特点,是众多Shell中比较常用的一种。
Bash命令行参数
在使用wget的时候,我喜欢加上一个-c的参数,这样可以让wget启用断点续传功能。这里的-c就是一个命令行参数。
在写c语言的时候,我们使用字符串数组存储命令行参数,像我们所熟悉的argv[]。当然我们也需要命令行参数的个数,这存储在名为argc的整型变量中。argc和argv是约定俗成的名称,当然你可以使用自己的名称作为main函数的形参。
在编写Bash脚本的时候,也同样可以使用命令行参数。在Bash函数中也可以使用参数,特殊的是,Bash中的函数是没有参数列表的,例如
function foo
这样便完成了一个函数头的定义,但是没有任何的形参名称,这是由于Bash中特殊的参数传递方法所致。
这里需要说明的是,在Bash编程中命令行参数和函数的形参都采用统一的规则。
Bash的函数规则
在Bash中,所有变量在赋值是赋值号左侧直接写变量名。而在引用变量的值时,变量名的左侧需要加上$符号。写过PHP脚本可能对此深有印象,不过PHP是赋值和引用都要写。
Bash的参数是按照位置传递的,而且自动给出变量名称,例如$1就表示第一个参数,当然$2就是第二个参数,参数之间用空格区分。这样你可以顺序写到$n(n表示一个正整数),有几个参数都可以按照顺序引用。
$0表示当前运行命令的名称,这个其实是特殊的参数,但是往往很少用到。
如果你想得到参数的个数,它保存在一个特殊名称的变量里,叫做$#。
$*和$@表示所有的参数,具体区别和其他一些特殊参数请见这里。
注:后面我们会用到一个$?参数,这表示上一条独立命令运行的结果。我们才c语言写程序的时候,常常以return 0作为程序正常退出的标志,这个0就被返回给Bash,而$?可以引用到上一个程序运行的结果。还记得Bash函数的参数和命令行参数是相同的吗?如果刚刚执行完一个Bash函数,$?里就保存着这个函数的运行结果,即return的值。
Bash的返回值
通常情况下Bash的函数是很少需要返回值的,但是有的时候需要,比如确定一个函数是否被成功执行,然后确定下一步的动作。这样的逻辑必须得到Bash函数的返回值,用以表示函数执行的状态。
在变写脚本时就遇到了这种需要,经过Google,获得两篇比较好的帖子:
英文:http://mail.linux.ie/pipermail/ilug/2008-March/097416.html (是一个邮件列表的邮件)
中文:http://blog.morebits.org/?p=83 (这里是一篇博文)
里面总结了5中Bash返回值的HACK方法:
1. 使用return返回(适用于数值)
myfun() {
return $(( 5 + 1 ));
}
myfun
RESULTS=$?
echo $RESULTS
这里的$?保存着函数运行的结果。
2. 使用echo(用echo返回结果,同样适用于数值)
myfun() {
echo $(( 5 + 1 ));
}
RESULTS=$(myfun)
echo $RESULTS
3. 近似全局变量的用法
myfun() {
foo=$(( 5 + 1 ));
}
myfun
RESULTS=$foo
echo $RESULTS
这里的$foo充当了全局变量的角色,将返回值从函数内带到函数外。
4. 使用地址传递参数
myfun() {
eval $1="\$(( 5 + 1 ))";
}
myfun RESULTS
echo $RESULTS
这里使用了一个函数参数$1带出返回值,这个方法非常类似与C++中的引用和C中的参数传址。从一个侧面反应了Bash在参数传递的时候应该都是传递的内存地址。
5. 使用地址传递(适用于数值)
myfun() {
let $1=5+1;
}
myfun RESULTS
echo $RESULTS
当然,以上这些方法可以单独使用,也可以结合使用。比如可以将传址和使用echo的方法结合起来:
function myfunc()
{
local __resultvar=$1
local myresult='some value'
if [[ "$__resultvar" ]]; then
eval $__resultvar="'$myresult'"
else
echo "$myresult"
fi
}
myfunc result
echo $result
result2=$(myfunc)
echo $result2
这样使用可以提供最大的灵活性。