完整版 Linux技巧:使用 bash function 命令自定义函数( 三 )


而 local var=$(foo); 语句使用 local 命令来定义 var 变量,执行 foo 函数,得到的 $? 却是 0,而foo 函数明明返回的是 1 。
原因就是该语句先通过 $(foo) 执行 foo 函数,然后用 local var 来定义 var 变量为局部变量,所以该语句对应的 $? 是 local 命令的返回值,而不是 foo 函数的返回值 。
当在函数外执行 local 命令时,它会报错,可以看到虽然 foobar 函数返回是 0,但是第三个 echo 语句打印的 $?是 1,正好是 local 命令执行出错时的返回值 。
即,对于 local var=$(func); 这种语句来说,它对应的 $? 不是所调用函数的返回值,而是local 命令的返回值 。
所以执行函数后,想用 $? 来判断函数的 return 返回值时,注意不要用这种写法 。
为了避免这种情况,最好在函数开头就用 local 命令声明所有局部变量 。
使用 local 声明多个变量时,变量之间用空格隔开,不要加逗号 。
举例说明如下:
local a b c;获取传入函数的所有参数在 bash 中,可以使用 $1、$2、$3、...、$n 的方式来引用传入函数的参数,$1 对应第一个参数值,$2 对应第二个参数值,依次类推 。
如果 n 的值大于 9,那么需要用大括号{}把 n 括起来 。
例如,${10} 表示获取第 10 个参数的值,写为 $10 获取不到第 10 个参数的值 。
实际上,$10 相当于 ${1}0,也就是先获取 $1 的值,后面再跟上 0,如果 $1 的值是 "first",则 $10 的值是 "first0" 。
下面通过一个 testparams.sh 脚本来举例说明,该脚本的内容如下:
#!/bin/bashfunction show_params(){echo $1 , $2 , $3 , $4 , $5 , $6 , $7 , $8 , $9 , $10 , ${10} , ${11}}show_params $@这个脚本把传入自身的参数传给 show_params 函数,该函数再打印出各个参数,使用 $10、${10} 这两个形式来说明它们的区别 。
执行 ./testparams.sh 脚本的结果如下:
$ ./testparams.sh 1a 2b 3c 4d 5e 6f 7g 8h 9i 10j 11k1a , 2b , 3c , 4d , 5e , 6f , 7g , 8h , 9i , 1a0 , 10j , 11k可以看到,传入的第 10 个参数值是 "10j",而 $10 打印出来的结果是 "1a0",也就是第一个参数 "1a" 后面再跟上 0 。
${10} 打印的结果才是第 10 个参数的值 。
相应地,${11} 也能正确打印第 11 个参数的值 。
$1、$2 这种写法在 bash 文档里面称之为 positional parameter,中文直译过来是 “位置参数” 。
查看 man bash 里面的说明如下:

Positional Parameters
A positional parameter is a parameter denoted by one or more digits, other than the single digit 0. Positional parameters are assigned from the shell's arguments when it is invoked, and may be reassigned using the set builtin command.
Positional parameters may not be assigned to with assignment statements. The positional parameters are temporarily replaced when a shell function is executed.
When a positional parameter consisting of more than a single digit is expanded, it must be enclosed in braces.
${parameter}
The value of parameter is substituted.
The braces are required when parameter is a positional parameter with more than one digit, or when parameter is followed by a character which is not to be interpreted as part of its name.
The parameter is a shell parameter or an array reference (Arrays).
可以看到,这里面提到了需要用大括号{}把大于9的数字括起来,{} 的作用是限定大括号里面的字符串是一个整体 。
例如,有一个 var 变量值是 "Test",现在想打印这个变量值,并跟着打印 "Hello" 字符串,也就是打印出来 "TestHello" 字符串,那么获取 var 变量值的语句和 "Hello" 字符串中间就不能有空格,否则 echo 命令会把这个空格一起打印出来,但是写为 $varHello 达不到想要的效果 。
具体举例如下:
$ var="Test"$ echo $var HelloTest Hello$ echo $varHello$ echo ${var}HelloTestHello可以看到,$var Hello 这种写法打印出来的 "Test" 和 "Hello" 中间有空格,不是想要的结果 。
而 $varHello 打印为空,这其实是获取 varHello 变量的值,这个变量没有定义过,默认值是空 。
${var}Hello 打印出了想要的结果,用大括号 {} 把 var 括起来,明确指定要获取的变量名是 var,避免混淆 。
上面贴出的 testparams.sh 脚本代码里面还用到了一个 $@ 特殊参数,它会扩展为 positional parameter 自身的列表 。
查看 man bash 的说明如下:
Special Parameters
@ Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word.


推荐阅读