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里面的函数了。

linux之函数的更多相关文章

  1. Linux open函数

    Linux open函数 open 函数用于打开和创建文件.以下是 open 函数的简单描述 #include <fcntl.h> int open(const char *pathnam ...

  2. linux内核函数库文件的寻找

    linux内核函数的so库文件怎么找呢? 首先还是要产生一个进程的coredump文件的 linux有一个lib-gdb.so库,这个进程的coredump文件中所有load段的最后一个load段中, ...

  3. linux select函数详解

    linux select函数详解 在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核: •我们所关心的文件描述符 •对每个描述符,我们所关心的状 ...

  4. Linux mmap函数简介

    一.简介 Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明: 头文件: ...

  5. 动态替换Linux核心函数的原理和实现

    转载:https://www.ibm.com/developerworks/cn/linux/l-knldebug/ 动态替换Linux核心函数的原理和实现 在调试Linux核心模块时,有时需要能够实 ...

  6. Linux getopt()函数 getopt_long()函数---转

    http://hi.baidu.com/scoundrelgg/item/d4083f8412eea05d26ebd97f Linux getopt()函数 getopt_long()函数 get_o ...

  7. linux 系统函数之 (dirname, basename)【转】

    转自:http://blog.csdn.net/peter_cloud/article/details/9308333 版权声明:本文为博主原创文章,未经博主允许不得转载. 除非你的原件考虑跨平台. ...

  8. linux C函数之strdup函数分析【转】

    本文转载自:http://blog.csdn.net/tigerjibo/article/details/12784823 linux C函数之strdup函数分析 一.函数分析 1.函数原型: #i ...

  9. [ARM-Linux开发]Linux open函数

    Linux open函数 open 函数用于打开和创建文件.以下是 open 函数的简单描述 #include <fcntl.h> int open(const char *pathnam ...

  10. linux execl()函数 关于execl()函数族的用法不在赘述,

    linux execl()函数 关于execl()函数族的用法不在赘述, linux 网络编程 1---(基本概念) 1.TCP和UDP协议 共同点:同为传输层协议 不同点: TCP:有连接,可靠 U ...

随机推荐

  1. GNU C中__attribute__

    __attribute__基本介绍: 1. __attribute__ 可以设置函数属性.变量属性和类型属性. 2. __attribute__ 语法格式为:__attribute__ ((attri ...

  2. inotifywait实时监控文件目录

    一.inotify简介 inotify 是一种强大的.细粒度的.异步文件系统监控机制,它满足各种各样的文件监控需要,可以监控文件系统的访问属性.读写属性.权限属性.创建删除.移动等操作,也可以监控文件 ...

  3. 嵌入式开发 centos7 交叉编译环境准备

    1. 安装centos7,启动图像化界面. 参考:https://blog.csdn.net/qq_23014435/article/details/74347925 # systemctl get- ...

  4. Nginx配置根据客户端设备转发

    #user nobody; worker_processes ; #error_log logs/error.log; #error_log logs/error.log notice; #error ...

  5. Olympic Class Ships【奥林匹克级邮轮】

    Olympic Class Ships You probably know about the Titanic, but it was actually just noe of three state ...

  6. Mysql密码加密方式

    以Mysql 4.1版本为分界线,两种加密方式 Mysql323加密:(16位) select  old_password('root'); //Mysql自带加密函数old_password(str ...

  7. v-model 的修饰符

    1..trim 自动过滤输入内容最开始 和 最后的 空格,中间的会保留一个空格,多的会被过滤掉 2..lazy 一般情况下,在input的 v-model是一直在同步 输入的内容与显示的内容,不过再添 ...

  8. 第三模块 面向对象& 网络编程基础 实战考核

    1.简述构造方法和析构方法. 构造方法(__init__):主要作用是实例化时给实例一些初始化参数,或执行一些其它的初始化工作,总之因为这个__init__只要一实例化, 就会自动执行,不管你在这个方 ...

  9. PHP的抽象类、接口的区别和选择

    1.对接口的使用是通过关键字implements.对抽象类的使用是通过关键字extends.当然接口也可以通过关键字extends继承. 2.接口中不可以声明成员变量(包括类静态变量),但是可以声明类 ...

  10. 获取获取docker的文件

    1.docke实例内mysql 导出文件 mysql -h yourhost -P yourport -u user -p dbname -e "select * from employee ...