linux的shell函数相关知识

来源:互联网 发布:哪些论坛分享软件 编辑:程序博客网 时间:2024/06/05 16:24

本文来自整理网络帖子,感谢大家分享。

一、Linux shell 函数参数

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...

带参数的函数示例:

#!/bin/bashfunWithParam(){    echo "The value of the first parameter is $1 !"    echo "The value of the second parameter is $2 !"    echo "The value of the tenth parameter is $10 !"    echo "The value of the tenth parameter is ${10} !"    echo "The value of the eleventh parameter is ${11} !"    echo "The amount of the parameters is $# !"    echo "The string of the parameters is $* !"}funWithParam 1 2 3 4 5 6 7 8 9 34 73

输出结果:

The value of the first parameter is 1 !The value of the second parameter is 2 !The value of the tenth parameter is 10 !The value of the tenth parameter is 34 !The value of the eleventh parameter is 73 !The amount of the parameters is 12 !The string of the parameters is 1 2 3 4 5 6 7 8 9 34 73 !"

注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

另外,还有几个特殊字符用来处理参数:

参数处理说明$#传递到脚本的参数个数$*以一个单字符串显示所有向脚本传递的参数$$脚本运行的当前进程ID号$!后台运行的最后一个进程的ID号$@与$*相同,但是使用时加引号,并在引号中返回每个参数。$-显示Shell使用的当前选项,与set命令功能相同。$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。注意:脚本命令输出的参数不能直接传递到函数中,只能在主程序中。


二、Linux shell 函数 返回值

Shell函数返回值,一般有3种方式:returnargvecho


1) return 语句
shell函数的返回值,可以和其他语言的返回值一样,通过return语句返回。
示例:

[javascript] view plain copy
 print?
  1. #!/bin/bash -  
  2. function mytest()  
  3. {  
  4.     echo "arg1 = $1"  
  5.     if [ $1 = "1" ] ;then  
  6.         return 1  
  7.     else  
  8.         return 0  
  9.     fi  
  10. }  
  11.   
  12. echo   
  13. echo "mytest 1"  
  14. mytest 1  
  15. echo $?         # print return result  
  16.   
  17. echo   
  18. echo "mytest 0"  
  19. mytest 0  
  20. echo $?         # print return result  
  21.   
  22. echo   
  23. echo "mytest 2"  
  24. mytest 2  
  25. echo $?         # print return result  
  26.   
  27.   
  28. echo  
  29. echo "mytest 1 = "`mytest 1`  
  30. if  mytest 1 ; then  
  31.     echo "mytest 1"  
  32. fi  
  33.   
  34. echo  
  35. echo "mytest 0 = "`mytest 0`  
  36. if  mytest 0 ; then  
  37.     echo "mytest 0"  
  38. fi  
  39.   
  40. echo  
  41. echo "if fasle" # if 0 is error  
  42. if false; then  
  43.     echo "mytest 0"  
  44. fi  
  45.   
  46.   
  47. echo  
  48. mytest 1  
  49. res=`echo $?`   # get return result  
  50. if [ $res = "1" ]; then  
  51.     echo "mytest 1"  
  52. fi  
  53.   
  54. echo  
  55. mytest 0  
  56. res=`echo $?`   # get return result  
  57. if [ $res = "0" ]; then  
  58.     echo "mytest 0"  
  59. fi  
  60.   
  61.   
  62.   
  63. echo   
  64. echo "end"  

结果:

mytest 1
arg1 = 1
1

mytest 0
arg1 = 0
0

mytest 2
arg1 = 2
0

mytest 1 = arg1 = 1
arg1 = 1

mytest 0 = arg1 = 0
arg1 = 0
mytest 0

if fasle

arg1 = 1
mytest 1

arg1 = 0
mytest 0

end

先定义了一个函数mytest,根据它输入的参数是否为1来return 1或者return 0.
获取函数的返回值通过调用函数,或者最后执行的值获得。
另外,可以直接用函数的返回值用作if的判断。
注意:return只能用来返回整数值,且和c的区别是返回为正确,其他的值为错误。


2) argv全局变量

这种就类似于C语言中的全局变量(或环境变量)。

示例:

[javascript] view plain copy
 print?
  1. #!/bin/bash -  
  2.   
  3. g_var=  
  4. function mytest2()  
  5. {  
  6.     echo "mytest2"  
  7.     echo "args $1"  
  8.     g_var=$1  
  9.   
  10.     return 0  
  11. }  
  12.   
  13. mytest2 1  
  14. echo "return $?"  
  15.   
  16. echo  
  17. echo "g_var=$g_var"  

结果:

mytest2
args 1
return 0

g_var=1


函数mytest2通过修改全局变量的值,来返回结果。


注: 以上两个方法失效的时候

以上介绍的这两种方法在一般情况下都是好使的,但也有例外。
示例:
[javascript] view plain copy
 print?
  1. #!/bin/bash -  
  2.   
  3.   
  4. function mytest3()  
  5. {  
  6.     grep "123" test.txt | awk -F: '{print $2}' | while read line ;do  
  7.         echo "$line"  
  8.         if [ $line = "yxb" ]; then  
  9.             return 0    # return to pipe only  
  10.         fi  
  11.     done  
  12.   
  13.     echo "mytest3 here "  
  14.     return 1            # return to main process  
  15. }  
  16.   
  17. g_var=  
  18. function mytest4()  
  19. {  
  20.     grep "123" test.txt | awk -F: '{print $2}' | while read line ;do  
  21.         echo "$line"  
  22.         if [ $line = "yxb" ]; then  
  23.             g_var=0  
  24.             echo "g_var=0"  
  25.             return 0    # return to pipe only  
  26.         fi  
  27.     done  
  28.   
  29.     echo "mytest4 here "  
  30.     return 1  
  31. }  
  32.   
  33. mytest3  
  34. echo $?  
  35.   
  36. echo  
  37. mytest4  
  38. echo $?  
  39.   
  40. echo  
  41. echo "g_var=$g_var"  

其中,test.txt 文件中的内容如下:

456:kkk
123:yxb
123:test

结果:

yxb
mytest3 here 
1

yxb
g_var=0
mytest4 here 
1

g_var=
可以看到mytest3在return了以后其实没有直接返回,而是执行了循环体后的语句,同时看到mytest4中也是一样,同时,在mytest4中,对全局变量的修改也无济于事,全局变量的值根本就没有改变。这个是什么原因那?
笔者认为,之所以return语句没有直接返回,是因为return语句是在管道中执行的,管道其实是另一个子进程,而return只是从子进程中返回而已,只是while语句结束了。而函数体之后的语句会继续执行。
同理,全局变量在子进程中进行了修改,但是子进程的修改没有办法反应到父进程中,全局变量只是作为一个环境变量传入子进程,子进程修改自己的环境变量,不会影响到父进程。
因此在写shell函数的时候,用到管道(cmd &后台进程也一样)的时候一定要清楚此刻是从什么地方返回。


3) echo 返回值

其实在shell中,函数的返回值有一个非常安全的返回方式,即通过输出到标准输出返回。因为子进程会继承父进程的标准输出,因此,子进程的输出也就直接反应到父进程。因此不存在上面提到的由于管道导致返回值失效的情况。
在外边只需要获取函数的返回值即可。

示例:

[javascript] view plain copy
 print?
  1. #!/bin/bash   
  2.  
  3. ##############################################  
  4. # Author : IT-Homer  
  5. # Date   : 2012-09-06   
  6. # Blog   : http://blog.csdn.net/sunboy_2050  
  7. ##############################################  
  8.   
  9. function mytest5()  
  10. {  
  11.     grep "123" test.txt | awk -F: '{print $2}' | while read line; do  
  12.         if [ $line = "yxb" ]; then  
  13.             echo "0"    # value returned first by this function  
  14.             return 0  
  15.         fi  
  16.     done  
  17.   
  18.     return 1  
  19. }  
  20.   
  21. echo '$? = '"$?"  
  22. result=$(mytest5)  
  23.   
  24. echo "result = $result"  
  25.   
  26. echo  
  27. if [ -z $result ]       # string is null  
  28. then  
  29.     echo "no yxb. result is empyt"  
  30. else  
  31.     echo "have yxb, result is $result"  
  32. fi  
结果:
$? = 0
result = 0

have yxb, result is 0

这个方式虽然好使,但是有一点一定要注意,不能向标准输出一些不是结果的东西,比如调试信息,这些信息可以重定向到一个文件中解决,特别要注意的是,用到比如grep这样的命令的时候,一定要记得1>/dev/null 2>&1来避免这些命令的输出。



0 0
原创粉丝点击