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


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

文章插图
 
定义函数的两种格式在 bash 中,定义函数时,function 关键字是可选的,查看man bash手册,里面提到定义函数的两种格式如下:
name () compound-command [redirection]
function name [()] compound-command [redirection]
从中可以看到,当不写 function 关键字时,函数名后面一定要跟着小括号(),而写了 function 关键字时,小括号是可选的 。
关于 compound-command 的说明,同样可以查看 man bash 手册,里面提到下面几种形式:
A compound command is one of the following:
(list) list is executed in a subshell environment. Variable assignments and builtin commands that affect the shell's environment do not remain in effect after the command completes. The return status is the exit status of list.
{ list; } list is simply executed in the current shell environment. list must be terminated with a newline or semicolon. The return status is the exit status of list.
常见的是 { list; } 这种形式,但是写为 (list) 也可以 。
举例说明如下:
$ testpwd() (pwd)$ testpwd/home/sample/$ testpwd() ( pwd )$ testpwd/home/sample/$ testpwd() (pwd;)$ testpwd/home/sample/这里定义了一个 testpwd 函数,它自身的代码是用小括号()括起来的 pwd 命令,这个命令跟 () 之间可以有空格,也可以没有空格 。
在命令后可以加分号,也可以不加分号 。
注意:使用 { list; } 这个写法时,在 list 后面一定要跟着分号';',否则会报错 。而且 list; 和左边的大括号 { 之间要有空格 。
如果写为 {list;} 会报错,而 { list;} 不会报错,建议还是写为 { list; } 的形式 。
举例说明如下:
$ lsfunc() {ls}-bash: syntax error near unexpected token `{ls}'$ function lsfunc() {ls;}-bash: syntax error near unexpected token `{ls'$ lsfunc() { ls;}$ lsfunchello.c调用 bash shell 的函数时,不需要写小括号(),只写函数名即可 。
例如执行上面的 lsfunc() 函数,直接写 lsfunc 就可以 。
如果写成 lsfunc() 反而变成重新定义这个函数 。
在函数名后面可以提供要传入的参数列表,不同参数之间用空格隔开 。
如果某个参数需要带有空格,要用引号把该参数括起来 。
从函数中返回内容Bash 要求函数的返回值必须为一个整数,不能用 return 语句返回字符串变量 。
一般来说,该整数返回值为 0,表示函数执行成功,非0 表示执行失败 。
在自定义的函数里面,执行 return 语句会退出函数,不会退出整个脚本 。
在函数里面执行 exit 语句则会退出整个脚本,而不是只退出函数 。
由于在函数内部用 return 返回,只能返回整数 。
如果想从函数内部把字符串传递到函数之外,可以用 echo 命令来实现,就是在函数内部打印字符串,然后调用者获取标准输出获取到打印的字符串 。
具体举例如下:
$ function foo() { echo "foo"; return 0; }$ var=$(foo)$ echo ${var}, $?foo, 0可以看到,打印结果是 "foo, 0" 。
此时看起来,这个函数像是返回了两个值,一个是通过 $(foo) 获取 foo 函数的标准输出,另一个是 $? 会获取函数通过 return 语句返回的 0 。
如果在函数中写为 return 1,那么上面的 $? 打印的出来的值是 1 。
下面再举例说明如下:
$ foo() { echo "foo"; }$ bar() { foo; }$ foobar() { a=$(foo); }$ var=$(foo); echo first: ${var}first: foo$ var=$(bar); echo second: ${var}second: foo$ var=$(foobar); echo third: ${var}third:可以看到,foo 函数将字符串写到标准输出,var=$(foo); 语句把 foo 函数的标准输出赋值给 var 变量,打印 var 变量的值是 "foo" 。
bar() 函数调用了 foo 函数,但是没有读取 foo 函数打印的标准输出,则这个标准输出会被 bar 函数继承,就好象这个标准输出是由 bar 函数输出一样,var=$(bar); 语句也会把 var 变量赋值为 "foo" 。
而 foobar 函数读取了 foo 函数的标准输出,foobar 函数自身没有用 echo 命令来输出内容,此时再通过 $(foobar) 来获取该函数的输出,会获取到空,因为 foo 函数中的标准输出给 foobar 读走了 。
注意:这种在函数内部通过 echo 命令输出字符串的做法有个缺陷,就是不能再在函数里面执行 echo 语句来打印调试信息,这些调试信息会被函数外的语句一起读取到,有用的结果和调试信息都混在一起,如果函数外的语句没有打印这些结果,就会看不到调试信息 。


推荐阅读