1基本的脚本函数

函数是一个脚本代码块,你可以为其命名并在代码中任何位置重用。要在脚本中使用该代码块时,只要使用所起的函数名就行了。

1.1创建函数

有两种格式可以用来在bash shell脚本中创建函数。第一种格式采用关键字function,后跟分配给该代码块的函数名。

  1. function name {
  2. commands
  3. }

二种格式更接近于其他编程语言中定义函数的方式。

  1. name() {
  2. commands
  3. }

1.2 使用函数

  1. $ cat test1
  2. #!/bin/bash
  3. # using a function in a script
  4. function func1 {
  5. echo "This is an example of a function"
  6. }
  7. count=1
  8. while [ $count -le 5 ]
  9. do
  10. func1
  11. count=$[ $count + 1 ]
  12. done
  13. echo "This is the end of the loop"
  14. func1
  15. echo "Now this is the end of the script"
  16.  
  17. $ ./test1
  18. This is an example of a function
  19. This is an example of a function
  20. This is an example of a function
  21. This is an example of a function
  22. This is an example of a function
  23. This is the end of the loop

函数定义的位置一定要在使用到该函数的位置之前。

2返回值

2.1默认退出状态码

默认情况下,函数的退出状态码是函数中最后一条命令返回的退出状态码。在函数执行结束后,可以用标准变量$?来确定函数的退出状态码。

  1. $ cat test4
  2. #!/bin/bash
  3. # testing the exit status of a function
  4. func1() {
  5. echo "trying to display a non-existent file"
  6. ls -l badfile
  7. }
  8. echo "testing the function: "
  9. func1
  10. echo "The exit status is: $?"
  11.  
  12. $ ./test4
  13. testing the function:
  14. trying to display a non-existent file
  15. ls: badfile: No such file or directory
  16. The exit status is: 1

函数的退出状态码是1,这是因为函数中的最后一条命令没有成功运行。但你无法知道函数中其他命令中是否成功运行。看下面的例子:

  1. $ cat test4b
  2. #!/bin/bash
  3. # testing the exit status of a function
  4. func1() {
  5. ls -l badfile
  6. echo "This was a test of a bad command"
  7. }
  8. echo "testing the function:"
  9. func1
  10. echo "The exit status is: $?"
  11.  
  12. $ ./test4b
  13. testing the function:
  14. ls: badfile: No such file or directory
  15. This was a test of a bad command
  16. The exit status is: 0

这次,由于函数最后一条语句echo运行成功,该函数的退出状态码就是0,尽管其中有一条命令并没有正常运行。

2.2使用return命令

return命令来退出函数并返回特定的退出状态码。return命令允许指定一个整数值来定义函数的退出状态码,从而提供了一种简单的途径来编程设定函数退出状态码。

  1. $ cat test5
  2. #!/bin/bash
  3. # using the return command in a function
  4. function dbl {
  5. read -p "Enter a value: " value
  6. echo "doubling the value"
  7. return $[ $value * 2 ]
  8. }
  9. dbl
  10. echo "The new value is $?"

dbl函数会将$value变量中用户输入的值翻倍,然后用return命令返回结果。脚本用$?变量显示了该值。

但当用这种方法从函数中返回值时,要小心了。记住下面两条技巧来避免问题:

  • 函数一结束就取返回值;
  • 退出状态码必须是0~255。

例如我们运行一下:

  1. $ ./test5
  2. Enter a value: 200
  3. doubling the value
    The new value is 144

2.3使用函数输出

可以用下面这种方法来获得任何类型的函数输出,并将其保存到变量中:

  1. result=$(dbl)

3在函数中使用变量

3.1 向函数传递参数

函数可以使用标准的参数环境变量来表示命令行上传给函数的参数。例如,函数名会在$0 变量中定义,函数命令行上的任何参数都会通过$1、$2等定义。也可以用特殊变量$#来判断传给函数的参数数目。

在脚本中指定函数时,必须将参数和函数放在同一行,像这样:

  1. func1 $value1 10

然后函数可以用参数环境变量来获得参数值。这里有个使用此方法向函数传值的例子。

  1. $ cat test6
  2. #!/bin/bash
  3. # passing parameters to a function
  4. function addem {
  5. if [ $# -eq 0 ] || [ $# -gt 2 ]
  6. then
  7. echo -1
  8. elif [ $# -eq 1 ]
  9. then
  10. echo $[ $1 + $1 ]
  11. else
  12. echo $[ $1 + $2 ]
  13. fi
  14. }
  15. echo -n "Adding 10 and 15: "
  16. value=$(addem 10 15)
  17. echo $value
  18. echo -n "Let's try adding just one number: "
  19. value=$(addem 10)
  20. echo $value
  21. echo -n "Now trying adding no numbers: "
  22. value=$(addem)
  23. echo $value
  24. echo -n "Finally, try adding three numbers: "
  25. value=$(addem 10 15 20)
  26. echo $value
  27.  
  28. $ ./test6
  29. Adding 10 and 15: 25
  30. Let's try adding just one number: 20
  31. Now trying adding no numbers: -1
  32. Finally, try adding three numbers: -1

由于函数使用特殊参数环境变量作为自己的参数值,因此它无法直接获取脚本在命令行中的参数值。

3.2在函数中处理变量

函数使用两种类型的变量:

  • 全局变量
  • 局部变量

默认情况下,你在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问:

  1. $ cat test8
  2. #!/bin/bash
  3. # using a global variable to pass a value
  4. function dbl {
  5. value=$[ $value * 2 ]
  6. }
  7. read -p "Enter a value: " value
  8. dbl
  9. echo "The new value is: $value"
  10.  
  11. $ ./test8
  12. Enter a value: 450
  13. The new value is: 900

函数内部使用的任何变量都可以被声明成局部变量。要实现这一点,只要在变量声明的前面加上local关键字就可以了。

  1. $ cat test9
  2. #!/bin/bash
  3. # demonstrating the local keyword
  4. function func1 {
  5. local temp=$[ $value + 5 ]
  6. result=$[ $temp * 2 ]
  7. }
  8. temp=4
  9. value=6
  10. func1
  11. echo "The result is $result"
  12. if [ $temp -gt $value ]
  13. then
  14. echo "temp is larger"
  15. else
  16. echo "temp is smaller"
  17. fi
  18.  
  19. $ ./test9
  20. The result is 22
  21. temp is smaller

4数组变量和函数

4.1 向函数传数组参数

如果你试图将该数组变量作为函数参数,函数只会取数组变量的第一个值。要解决这个问题,你必须将该数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,可以将所有的参数重新组合成一个新的变量。下面是个具体的例子:

  1. $ cat test10
  2. #!/bin/bash
  3. # array variable to function test
  4. function testit {
  5. local newarray
  6. newarray=($(echo "$@"))
  7. echo "The new array value is: ${newarray[*]}"
  8. }
  9. myarray=(1 2 3 4 5)
  10. echo "The original array is ${myarray[*]}"
  11. testit ${myarray[*]}
  12.  
  13. $ ./test10
  14. The original array is 1 2 3 4 5
  15. The new array value is: 1 2 3 4 5

该脚本用$myarray变量来保存所有的数组元素,然后将它们都放在函数的命令行上。该函数随后从命令行参数中重建数组变量。在函数内部,数组仍然可以像其他数组一样使用。

  1. $ cat test11
  2. #!/bin/bash
  3. # adding values in an array
  4. function addarray {
  5. local sum=0
  6. local newarray
  7. newarray=($(echo "$@"))
  8. for value in ${newarray[*]}
  9. do
  10. sum=$[ $sum + $value ]
  11. done
  12. echo $sum
  13. }
  14. myarray=(1 2 3 4 5)
  15. echo "The original array is: ${myarray[*]}"
  16. result=$(addarray ${myarray[*]})
  17. echo "The result is $result"
  18.  
  19. $ ./test11
  20. The original array is: 1 2 3 4 5
  21. The result is 15

addarray函数会遍历所有的数组元素,将它们累加在一起。你可以在myarray数组变量中放置任意多的值,addarry函数会将它们都加起来。

4.2从函数返回数组

从函数里向shell脚本传回数组变量也用类似的方法。函数用echo语句来按正确顺序输出单个数组值,然后脚本再将它们重新放进一个新的数组变量中。

  1. #!/bin/bash
  2. function test {
  3. local array
  4. local newarray
  5. array=($(echo "$@"))
  6. sum=0
  7. for val in ${array[*]}
  8. do
  9. newarray[$sum]=$[$val*2]
  10. sum=$[$sum+1]
  11. done
  12. echo ${newarray[*]}
  13. }
  14. myarray=(1 2 3 4 5)
  15. echo "array: ${myarray[*]}"
  16. array=$(test ${myarray[*]})
  17. echo ${array[*]}
  18.  
  19. $ ./test12
  20. array: 1 2 3 4 5
  21. 2 4 6 8 10

5函数递归

  1. $ cat test13
  2. #!/bin/bash
  3. # using recursion
  4. function factorial {
  5. if [ $1 -eq 1 ]
  6. then
  7. echo 1
  8. else
  9. local temp=$[ $1 - 1 ]
  10. local result=$(factorial $temp)
  11. echo $[ $result * $1 ]
  12. fi
  13. }
  14. read -p "Enter value: " value
  15. result=$(factorial $value)
  16. echo "The factorial of $value is: $result"
  17.  
  18. $ ./test13
  19. Enter value: 5
  20. The factorial of 5 is: 120

6创建库

使用函数可以在脚本中省去一些输入工作,这一点是显而易见的。但如果你碰巧要在多个脚本中使用同一段代码呢?显然,为了使用一次而在每个脚本中都定义同样的函数太过麻烦。有个方法能解决这个问题!bash shell允许创建函数库文件,然后在多个脚本中引用该库文件。

第一步是创建一个包含脚本中所需函数的公用库文件

  1. $ cat myfuncs
  2. # my script functions
  3. function addem {
  4. echo $[ $1 + $2 ]
  5. }
  6. function multem {
  7. echo $[ $1 * $2 ]
  8. }
  9. function divem {
  10. if [ $2 -ne 0 ]
  11. then
  12. echo $[ $1 / $2 ]
  13. else
  14. echo -1
  15. fi
  16. }

第二步是在用到这些函数的脚本文件中包含myfuncs库文件。(用source命令)

使用函数库的关键在于source命令。source命令有个快捷的别名,称作点操作符。要在shell脚本中运行myfuncs 库文件,只需添加下面这行:

  1. . ./myfuncs

所以,这里有个用myfuncs库文件创建脚本的例子:

  1. $ cat test14
  2. #!/bin/bash
  3. # using functions defined in a library file
  4. . ./myfuncs
  5. value1=10
  6. value2=5
  7. result1=$(addem $value1 $value2)
  8. result2=$(multem $value1 $value2)
  9. result3=$(divem $value1 $value2)
  10. echo "The result of adding them is: $result1"
  11. echo "The result of multiplying them is: $result2"
  12. echo "The result of dividing them is: $result3"
  13.  
  14. $ ./test14
  15. The result of adding them is: 15
  16. The result of multiplying them is: 50
  17. The result of dividing them is: 2

7在命令行上使用函数

7.1在命令行上创建函数

因为shell会解释用户输入的命令,所以可以在命令行上直接定义一个函数。有两种方法。

一种方法是采用单行方式定义函数。

  1. $ function divem { echo $[ $1 / $2 ]; }
  2. $ divem 100 5
  3. 20

当在命令行上定义函数时,你必须记得在每个命令后面加个分号,这样shell就能知道在哪里是命令的起止了。

  1. $ function divem { echo $[ $1 / $2 ]; }
  2. $ divem 100 5
  3. 20

另一种方法是采用多行方式来定义函数。在定义时,bash shell会使用次提示符来提示输入更多命令。用这种方法,你不用在每条命令的末尾放一个分号,只要按下回车键就行:

  1. $ function multem {
  2. > echo $[ $1 * $2 ]
  3. > }
  4. $ multem 2 5
  5. 10

在函数的尾部使用花括号,shell就会知道你已经完成了函数的定义。

7.2.bashrc 文件中定义函数

bash shell在每次启动时都会在主目录下查找这个文件,所以把函数写在.bashrc文件里面,每次启动一个新shell的时候,都会由shell重新载入。

1. 直接定义函数

  1. $ cat .bashrc
  2. # .bashrc
  3. # Source global definitions
  4. if [ -r /etc/bashrc ]; then
  5. . /etc/bashrc
  6. fi
  7.  
  8. function addem {
  9. echo $[ $1 + $2 ]
  10. }
  11. $ cat .bashrc
  12. # .bashrc
  13. # Source global definitions
  14. if [ -r /etc/bashrc ]; then
  15. . /etc/bashrc
  16.                                 

2. 读取函数文件

  1. $ cat .bashrc
  2. # .bashrc
  3. # Source global definitions
  4. if [ -r /etc/bashrc ]; then
  5. . /etc/bashrc
  6. fi
  7.  
  8. . /home/rich/libraries/myfuncs

Shell编程—创建函数的更多相关文章

  1. shell高级-----创建函数

    基本脚本函数 1.创建函数 有两种格式可以用来在bash shell脚本中创建函数.第一种采用关键字function.后跟分配给该代码的函数名. function name { commands } ...

  2. mysql编程--创建函数出错的解决方案

    本文章转载自:http://www.jb51.net/article/71100.htm 在使用MySQL数据库时,有时会遇到MySQL函数不能创建的情况.下面就教您一个解决MySQL函数不能创建问题 ...

  3. shell编程之函数

    一.函数定义和调用 函数是Shell脚本中自定义的一系列执行命令,一般来说函数应该设置有返回值(正确返回0,错误返回非0).对于错误返回,可以定义其他非0正值来细化错误.使用函数最大的好处是可避免出现 ...

  4. Linux&shell之高级Shell脚本编程-创建函数

    写在前面:案例.常用.归类.解释说明.(By Jim) 使用函数 #!/bin/bash # testing the script function myfun { echo "This i ...

  5. linux shell 进阶篇、shell脚本编程-创建函数

    使用函数 #!/bin/bash # testing the script function myfun { echo "This is an example of a function&q ...

  6. shell编程 之 函数

    1 函数基本格式 个人认为,编程中的函数基本上有3种,第一种是糖葫芦函数,一根棒棒串起来,执行一次就是走个过场,吃完了糖葫芦就没别的事了,第一种基本就是这样的: 它没有参数,没有返回值. demoFu ...

  7. Linux - 简明Shell编程08 - 函数(Function)

    脚本地址 https://github.com/anliven/L-Shell/tree/master/Shell-Basics 示例脚本及注释 #!/bin/bash function Check( ...

  8. shell 编程之函数

    shell 函数的定义和普通的c语言函数定义差不多 function(){ } shell 函数的返回值,可以显示的return 语句,如果没有return  那么就会把最后一条语句的执行结果作为返回 ...

  9. Shell 编程(函数)

    声明函数 demoFun(){ echo "这是我的第一个 shell 函数!" } 函数名(){ ...函数体 } 在Shell中,调用函数时可以向其传递参数.在函数体内部,通过 ...

随机推荐

  1. Django学习路37_request属性

      打印元信息,基本上都会打印出来 类字典结构的 key 键 允许重复   get 请求可以传参,但是长度有限制 最大不能超过 2K post 文件上传使用 get 参数 默认放在网址中 post 在 ...

  2. FPGA内部IP核DDS

    项目当中需要正弦信号与余弦信号,首先想到了DDS芯片,例如AD9833.AD9834.由于还需要用FPGA   做一些数据处理,后来干脆直接用FPGA 内部的DDSIP核,同时根据IP核内部的相位累加 ...

  3. PHP krsort() 函数

    ------------恢复内容开始------------ 实例 对关联数组按照键名进行降序排序: <?php$age=array("Peter"=>"35 ...

  4. PHP uniqid() 函数

    实例 生成一个唯一的 ID: <?phpecho uniqid();?>高佣联盟 www.cgewang.com 定义和用法 uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ...

  5. 7.29 NOI模拟赛 题答 npc问题 三染色 随机 贪心

    LINK:03colors 这道题虽然绝大多数的人都获得了满分 可是我却没有. 老师讲题的时候讲到了做题答的几个技巧 这里总结一下. 数据强度大概为n=5000,m=60000的随机数据. 老师说:一 ...

  6. luogu P1712 [NOI2016]区间 贪心 尺取法 线段树 二分

    LINK:区间 没想到尺取法. 先说暴力 可以发现答案一定可以转换到端点处 所以在每个端点从小到大扫描线段就能得到答案 复杂度\(n\cdot m\) 再说我的做法 想到了二分 可以进行二分答案 从左 ...

  7. 2020牛客暑假多校训练营 第二场 H Happy Triangle set 线段树 分类讨论

    LINK:Happy Triangle 这道题很容易. 容易想到 a+b<x a<x<b x<a<b 其中等于的情况在第一个和第三个之中判一下即可. 前面两个容易想到se ...

  8. ZROI 提高十连测 DAY2

    总结:入题尽量快,想到做法要先证明是否正确是否有不合法的情况,是否和题目中描述的情景一模一样.    不要慌 反正慌也拿不了多少分,多分析题目的性质如果不把题目的性质分析出来的话,暴力也非常的难写,有 ...

  9. 用Python做一个简单的翻译工具

    编程本身是跟年龄无关的一件事,不论你现在是十四五岁,还是四五十岁,如果你热爱它,并且愿意持续投入其中,必定会有所收获. 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过 ...

  10. @RequestMapping 参数详解

    引言: 前段时间项目中用到了RESTful模式来开发程序,但是当用POST.PUT模式提交数据时,发现服务器端接受不到提交的数据(服务器端参数绑定没有加任何注解),查看了提交方式为applicatio ...