可以将shell脚本代码放进函数中封装起来,这样就能在脚本中的任何地方多次使用它了。

17.1 基本的脚本函数

函数:是一个脚本代码块,可以为其命名并在代码中任何位置重用。

17.1.1 创建函数

有两种格式:name 是函数名

1)

function name

{

         commands

}

2)这种就比较接近c语言风格了

name()

{

         commands

}

17.1.2 使用函数

跟其他shell命令一样,在行中指定函数名就好了。

在函数定义前使用函数,会收到一条错误消息。

函数名是唯一的,如果重定义了函数,新的会覆盖旧的,并且不会产生任何错误消息。

例子:

  1 #!/bin/bash

  2

  3 function fun

  4 {

  5         echo "hahahaha, i am a function"

  6 }

  7

  8 count=1

  9 while [ $count -lt 5 ]

 10 do

 11         fun

 12         count=$[ $count + 1 ]

 13 done

 14

 15 fun2  # Error fun2 not define

 16 fun2() # 声明函数的另外一种方式

 17 {

 18         echo "I am Fun2, hahaha"

 19 }

 20 fun2

17.2 返回值

函数运行结束会返回一个退出状态码,有3种方法为函数生成退出状态码。

17.2.1 默认退出状态码

在函数结束时用 $? 来确定函数的退出状态码。

比如:

fun

echo “return code:$?”

如果函数最后执行的语句失败了,这里就会返回非0,最后成功了(不管前面有没有失败)返回都是0.

17.2.2 使用return命令

bashshell使用return命令来退出函数并返回特定的退出状态码。return允许指定一个整数值来定义函数的退出状态码。

注意:

函数一结束就要立即取返回值

退出状态码必须是0 – 255.(大于255会产生一个错误值)

17.2.3 使用函数输出

可以将函数输出(任何类型的函数输出)保存到shell变量中。

语法:result=$(fun)  这个命令会将fun函数的输出赋给$result变量

例子:

  1 #!/bin/bash

  2

  3 function fun

  4 {

  5         echo "hahahaha, i am a function"

  6         return 1

  7 }

  8

  9 fun

 10 echo "fun return $?"

 11

 12 function fun2

 13 {

 14         echo "This is Function fun2"

 15         read -p "Enter a value:" num

 16         echo $[ $num * 2 ]

 17 }

 18

 19 #fun2 # 如果加上这句就会调两次了。

 20 result=$(fun2)

 21 echo "fun2 return:$result"

这样就可以返回浮点数和字符串了。

17.3 在函数中使用变量

介绍一些处理shell脚本函数内外变量的方法

17.3.1 向函数传递参数

就跟向脚本传递参数一样,可以用$# $0 $1 $2

注意脚本主体的$1 $2 和传到函数里面的并不相同。

例子:

  1 #!/bin/bash

  2 function add

  3 {

  4         if [ $# -eq 0 ] || [ $# -gt 2 ]

  5         then

  6                 echo -1

  7         elif [ $# -eq 1 ]

  8         then

  9                 echo $[ $1 + $1 ]

 10         else

 11                 echo $[ $1 + $2 ]

 12         fi

 13 }

 14

 15 #ret=$(add)

 16 #ret=$(add 34) # 这里说明的如何传入参数

 17 ret=$(add 23 18)

 18 if [ $ret -eq -1 ]

 19 then

 20         echo "Function add Error"

 21 else

 22         echo "The value = $ret"

 23 fi

 24

 25 if [ $# -eq 2 ] # 这个的脚本主体接收的参数个数

 26 then

 27         echo "The value is $(add $1 $2)" # 将脚本主体的参数传给里面的函数

 28 else

 29         echo "Input Error"

 30 fi

17.3.2 在函数中处理变量

变量的作用域比较麻烦。作用域是变量可见的区域。

函数中定义的变量和普通变量的作用域不同,也就是说对脚本的其他部分来说它们是隐藏的

函数使用两种类型的变量:全局变量和局部变量

1.全局变量

是指在shell脚本中任何地方都有效的变量。

在脚本主体部分定义了全局变量,那么在函数内可以读取它的值。

在函数内定义了全局变量,在脚本的主体部分也可以读取它的值。

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

这样要特别注意变量的使用。很容易就改变了变量。

2.局部变量

可以在函数内部使用的任何变量都声明成局部变量。

在变量声明前加上local关键字就好了

local temp

例子:

  1 #!/bin/bash

  2 function fun

  3 {

  4         #temp=$[ $value + 5 ] # 如果这个是全局变量下面的结果就会异常

  5         local temp=$[ $value + 5 ]

  6         ret=$[ $temp * 2 ]

  7 }

  8

  9 temp=4

 10 value=6

 11 fun

 12 echo "fun: ret = $ret"

 13 if [ $temp -gt $value ]

 14 then

 15         echo "temp is big"

 16 else

 17         echo "value is big"

 18 fi

17.4 数组变量和函数

第6章讨论了数组来在单个变量中保存多个值的高级用法

17.4.1 向函数传数组参数

复习一下数组的用法:

定义方法1:初始化数组 array=(a b c)

定义方法2:新建数组并添加原色  array[数组]=元素

定义方法3:将命令输出作为数组元素 array=($(command))

数组操作:

1)获取所有元素:echo ${array[*]}

2)获取第n个元素: echo ${array[n]}    n为数组下标

3)添加元素:array[3]=d

4)删除元素:unset array[n] n为数组下标

1. 数组作为参数传递时不能用 $arrayName。

应该这样: fun ${arrName[*]}

还可以加上双引号。

例子:

  1 #!/bin/bash

  2 function testit

  3 {

  4         echo "The param are:$@, Param count:$#"

  5         thisarray=$1

  6         echo "The received array is:${thisarray[*]}"

  7

  8         for param in "$@"

  9         do

 10                 echo "Param = $param"

 11         done

 12 }

 13

 14 myarray=(13 25 35 45 55 65)

 15 echo "The original array is: ${myarray[*]}"

 16 testit "${myarray[*]}"

 17 testit ${myarray[*]}

有双引号时,函数接受的参数个数为1.

17.4.2 从函数返回参数

函数用echo语句来按正确顺序输出单个数组值,然后脚本再将它们重新放进一个新的数组变量中。

例子:

  1 #!/bin/bash

  2 function fun

  3 {

  4         local origarray

  5         local newarray

  6         local count

  7         local i

  8         origarray=($(echo "$@"))

  9         newarray=($(echo "$@"))

 10         count=$[ $# - 1 ]

 11         for (( i = 0; i <= count; i++ ))

 12         {

 13                 newarray[$i]=$[ ${origarray[$i]} * 2 ]

 14         }

 15         echo ${newarray[*]}

 16 }

 17

 18 myarr=(1 2 3 4 5 6 7 8 9 10 11 12 13 14)

 19 echo "original arr is: ${myarr[*]}"

 20 arg1=$(echo ${myarr[*]}) # 这里的用命令输出定义数组

 21 ret=($(fun $arg1))

 22 echo "new arr is: ${ret[*]}"

用arg1变量将数组值传给函数fun。函数将该数组重组到新的数组变量中。

脚本用fun函数的输出来重新生成一个新的数组变量

17.5 函数递归

函数的返回值直接用echo传递了。

例子:求阶乘(注意书上的例子p369 中间部分的 result ** 写错了)

  1 #!/bin/bash

  2 function fun1

  3 {

  4         if [ $1 -eq 1 ]

  5         then

  6                 echo 1

  7         else

  8                 local temp=$[ $1 - 1 ]

  9                 local ret=$(fun1 $temp)

 10                 echo $[ $ret * $1 ]

 11         fi

 12 }

 13

 14 read -p "Enter value:" value

 15 ret=$(fun1 $value)

 16 echo "ret = $ret"

17.6 创建库

允许创建函数库文件,然后在多个脚本中引用该库文件。

假设有个脚本,myfuncs。里面定义了一些函数:

 1 function addem

  2 {

  3         echo $[ $1 + $2 ]

  4 }

  5

  6 function multem

  7 {

  8         echo $[ $1 * $2 ]

  9 }

 10

 11

 12 function divem

 13 {

 14         if [ $2 -ne 0 ]

 15         then

 16                 echo $[ $1 / $2 ]

 17         else

 18                 echo -1

 19         fi

 20 }

shell函数仅在定义它的shell会话中有效。

如果你在shell命令行界面的提示符下运行myfuncs shell脚本,shell会创建一个新的shell并在其中运行这个脚本。

它会为那个新的shell定义这里面的函数,但当你运行另外一个要用到这些函数的脚本时,它们是无法使用的。

如何使用:使用函数库的关键在于source命令,source命令会在当前的shell上下文中执行命令。而不是创建一个新的shell。

source命令有个快捷的别名,称作点操作符。

如何使用: . ./myfuncs

这里假定在同一目录,如果不在,则需要指定相应的路径名。

实例:

1 #!/bin/bash

  2 . ./myfuncs

  3

  4 value1=10

  5 value2=5

  6 echo "Add Test ret = $(addem $value1 $value2)"

  7 echo "Mult Test ret = $(multem $value1 $value2)"

  8 echo "Div Test ret = $(divem $value1 $value2)"

17.7 在命令行上使用函数

17.7.1 在命令行上创建函数

可以在命令行界面的提示符下直接使用函数。

用起来就跟命令一样。而且一旦定义的函数,就可以在整个系统中使用它了,不需要管PATH环境变量了。

例子:

注意:

1)必须在每个命令后面加上分号,这样才能知道哪里是命令的起止

2)不能创建跟内建命令或其他命令相同的函数,否则会覆盖原来的命令

17.7.2 在.bashrc文件中定义函数

在命令行数定义shell函数明显的缺点是退出shell时,函数就消失了。

解决方法:将函数定义在一个特定的位置,这个位置在每次启动一个新的shell的时候都由shell重新载入。

最佳地点就是.bashrc。bash shell在每次启动时都会在主目录查找这个文件

1. 直接定义函数

直接在.bashrc后面加上

function addem

{

         echo $[ $1 + $2 ]

}

这样在系统上任意地方使用这个函数了。

2.读取函数文件

可以用source命令将库文件中的函数添加到.bashrc中

直接在.bashrc后面加上

.  /home/xcy/myfuncs

这样就可以用myfuncs里面的函数了。

17.8 实例

本节介绍GNU shtool shell 脚本函数库。shtool库提供了一些简单的shell脚本库。这里暂时不写了。

《Linux命令行与shell脚本编程大全》第十七章 创建函数的更多相关文章

  1. 《Linux命令行与shell脚本编程大全》23章24章

    第二十三章 使用其他shell bash shell是linux发行版中最广泛使用的shell.但是它并不是唯一的选择,还有其他的shell可以供你选择. 23.1 什么是dash shell 百度百 ...

  2. 《Linux命令行与shell脚本编程大全》第九章 安装软件程序

    包管理系统(PMS):用来进行软件安装.管理和删除的命令行工具 9.1包管理基础 1.主流的Linux发行版都采用了某种形式的包管理系统来控制软件和库的安装 2.PMS用一个数据库来记录:系统上安装了 ...

  3. Linux命令行与shell脚本编程大全.第3版(文字版) 超清文字-非扫描版 [免积分、免登录]

    此处免费下载,无需账号,无需登录,无需积分.收集自互联网,侵权通知删除. 点击下载:Linux命令行与shell脚本编程大全.第3版 (大小:约22M)

  4. 《Linux命令行与shell脚本编程大全 第3版》创建实用的脚本---11

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

  5. 《Linux命令行与shell脚本编程大全 第3版》高级Shell脚本编程---47

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

  6. 《Linux命令行与shell脚本编程大全 第3版》Shell脚本编程基础---57

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

  7. 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---57

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

  8. 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---56

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

  9. 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---55

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

  10. 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---54

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

随机推荐

  1. [问题记录]父元素position:relative的深坑

    个人博客迁移至:https://blog.plcent.com/欢迎大家访问 今天在写全屏切换的时候,发现一个问题就是切换时只能滚动第一屏,其他屏死都不动, 全屏滚动的原理: 是每次滚动父元素向上滚动 ...

  2. spring框架应用系列一:annotation-config自动装配

    本文系作者原创,转载请注明出处:http://www.cnblogs.com/further-further-further/p/7716678.html 解决问题 通过spring XML配置文件, ...

  3. APP在模拟器崩溃,提示__gcd_queue_item_enqueue_hook_block_invoke

    libBacktraceRecording.dylib`__gcd_queue_item_enqueue_hook_block_invoke: libBacktraceRecording.dylib` ...

  4. JAVA基础知识总结:四

    一.方法 1.什么是方法? 对于功能相同的代码段,为了简化代码,会把功能相同的代码抽取出来,方便多次使用,Java中,我们使用[方法],也被称为函数 2.函数的声明 语法: 访问权限修饰符 其他修饰符 ...

  5. 双向链表--Java实现

    /*双向链表特点: *1.每个节点含有两个引用,previos和next,支持向前或向后的遍历(除头节点) *2.缺点插入或删除的时候涉及到引用修改的比较多 *注意:下面的双向链表其实也实现了双端链表 ...

  6. LeetCode 33. Search in Rotated Sorted Array(在旋转有序序列中搜索)

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  7. xml文件的方式实现动态代理基于SpringAOP

    1.配置spring容器 导入jar包 com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.j ...

  8. JavaScript+HTML5 实现打地鼠小游戏

    一.游戏简介 打地鼠这个游戏相信大家都不陌生,也是童年时候一款经典的游戏.本次游戏的编写是以html文件形式完成的,并且使用HBulider软件进行编写,使用谷歌浏览器展示效果,游戏将会采用JavaS ...

  9. Python学习第一周

    一.我的第一个程序 print("Hello word!") 所以说python是一款非常简洁的语言,不像c,c++等等写一个简单的小程序还要调用一堆库.另外,python 3的版 ...

  10. JS基础 复习: Javascript的书写位置

    爱创课堂JS基础 复习: Javascript的书写位置复习 js书写位置:body标签的最底部.实际工作中使用书写在head标签内一对script标签里.alert()弹出框.console.log ...