[Shell]函数基础
2014-09-29 14:05
267 查看
1. 创建函数并简单调用:
2. 重名覆盖:
3. 退出函数:
正常退出:是指函数执行完最后一条命令后自然地退出函数,退出码则是最后一条命令的状态码
return命令退出:利用return命令退出,在使用return命令的位置退出,并可以指定一个退出状态码(以return命令的参数的形式体现)
查看函数的推出状态码:使用标准变量$?查看
使用退出状态码的缺陷:
1) 函数已退出就返回
2) 退出状态码的范围限制在0 ~ 255,一旦使用return返回一个超过255的数就会发生错误(模除256的结果)
3) 函数退出后必须第一时间使用$?查看,如果中间隔着其它命令则真正的返回值将会不存在
4. 函数输出:
5. 像使用命令行参数一样向函数传递参数:
由于函数的实质就是一个小脚本,在脚本中调用函数其实就是在该脚本中调用函数的位置再运行函数这个小脚本,因此函数也是一种脚本命令,也具有命令行参数,传参就是使用命令行参数,可以像使用命令行参数的方式在函数中使用传进来的参数。
注意!函数中的$1、$#等是调用函数时穿进去的命令行参数而不是调用它的脚本的命令行参数,要向函数传脚本的命令行参数则必须使用`add $1 $2`的形式
6. 全局变量:
7. 创建库并使用source命令导入库:
8. 在命令行上直接使用函数:
方法一:直接在命令行上定义
注意!以上两种方法中,如果定义的函数和内部命令名相同会覆盖内部命令,但不过在退出终端后这些函数将失效!
方法三:在bash启动文件.bashrc中定义函数,这样就可以当做内部命令使用,并且是永久有效的,.bashrc是bash的配置文件,位于用户主目录下
直接在.bashrc中将函数定义写上去或者使用source命令将函数库导入到.bashrc文件中,这样就可以在命令行上把这些函数当做内部命令来使,因为和内部命令是平起平坐的,因此也可以在任何脚本中像使用ls命令一般直接使用这些函数。
注意!修改后需要重新启动终端才能真正起作用。
9. 递归:
10. 可变数组:
11. 和函数之间传递可变数组的问题:
将数组传入函数并在函数中当做数组使用:
#!/bin/bash #一下两种函数定义完全等价 function f1 { echo This is func1 } f2() { echo This is func2 } #调用只需要简单地使用函数名就行了 f1 f2注意!一定要先定义再调用,否则会报错,和C语言不同的是C可以先声明在调用而定义可以放在任何位置,Shell必须把定义放在调用之前,并且没有声明!
2. 重名覆盖:
#!/bin/bash function f1 { echo This is func1 } f1 f1() { #从重复定义的位置开始就把上一个函数的代码完全覆盖了 echo This is func2 } f1 #输出的是func2
3. 退出函数:
正常退出:是指函数执行完最后一条命令后自然地退出函数,退出码则是最后一条命令的状态码
return命令退出:利用return命令退出,在使用return命令的位置退出,并可以指定一个退出状态码(以return命令的参数的形式体现)
查看函数的推出状态码:使用标准变量$?查看
使用退出状态码的缺陷:
1) 函数已退出就返回
2) 退出状态码的范围限制在0 ~ 255,一旦使用return返回一个超过255的数就会发生错误(模除256的结果)
3) 函数退出后必须第一时间使用$?查看,如果中间隔着其它命令则真正的返回值将会不存在
#!/bin/bash func() { echo The first time ls xxxx #最后一句异常,退出非0 } func echo $? #非0 func() { ls xxxx echo The second time #最然上一句有异常,但是最后一句正常,退出0 } func echo $? #0,因此正常退出通常有漏洞 func() { read -p "Please input a number: " a if [ $a -gt 5 ] #可以利用分支情况选择性退出 then return 1 else return 0 fi } func echo $?
4. 函数输出:
#!/bin/bash func() { read -p "Please input a number: " num echo $num } x=`func` #本来流向STDOUT的文本作为函数的输出返回给变量x,函数输出自动重定向到变量中 echo the func output a number: $x
5. 像使用命令行参数一样向函数传递参数:
由于函数的实质就是一个小脚本,在脚本中调用函数其实就是在该脚本中调用函数的位置再运行函数这个小脚本,因此函数也是一种脚本命令,也具有命令行参数,传参就是使用命令行参数,可以像使用命令行参数的方式在函数中使用传进来的参数。
#!/bin/bash add() { if (( 0 == $# || $# > 2 )) #检查参数的个数,0或者大于2个参数都返回-1 then echo -1 elif (( 1 == $# )) #一个参数则自加一遍返回 then echo $[ $1 + $1 ] else #两个参数相加返回 echo $[ $1 + $2 ] fi } while read -p "Please input numbers: " s ans=`add $s` #将读入的字符串作为传命令行参数传给函数 [ $ans -ne -1 ] #当返回值不为-1时打印结果,否则无限循环下去 do echo Answer is $ans done
注意!函数中的$1、$#等是调用函数时穿进去的命令行参数而不是调用它的脚本的命令行参数,要向函数传脚本的命令行参数则必须使用`add $1 $2`的形式
6. 全局变量:
#!/bin/bash function func { a=sdflsf #如果函数内部的变量不加任何属性关键字就会把它当做全局变量处理 echo inner first b: $b #定义local之前的b是外部的全局变量 local b=xxxxx #加local关键字后就声明为一个局部变量了,如果函数外有同名变量,则这两个变量时分离的,互不干涉 echo inner second b: $b #从定义local开始后的位置就都是局部变量的作用域了,因此这里访问的是局部变量 } func echo outer a: $a #虽然在函数内部使用,但是可以在外部访问,并且其值就是函数内部给它赋的值,因此这里的a和函数内的a是同一个a,没有分离 s=sdlfkjsdf #当然,这显示是在函数外直接定义了一个全局变量,在任何函数内都可以使用 echo outer b: $b #由于和函数内的b是分离的,因此这里的b是空的 b=sdfdsf func
7. 创建库并使用source命令导入库:
#!/bin/bash #库文件,里面只有函数定义 #funcs.sh function add { echo $[ $1 + $2 ] } function mul { echo $[ $1 * $2 ] } function div { if [ $2 -ne 0 ] then echo $[ $1 / $2 ] else echo Divide by zero! fi }
#!/bin/bash #.操作就相当于source命令,和source ./funcs.sh,这样就将其他脚本作为模块导入当前脚本中了,可以直接在当前脚本中使用库文件中的函数 . ./funcs.sh read a b add $a $b read a b mul $a $b read a b div $a $b第二个main.sh导入funcs.sh库使用里面的函数。
8. 在命令行上直接使用函数:
方法一:直接在命令行上定义
#定义在一行的情况 $ function add { echo $[ $1 + $2 ]; } #注意!在命令行上定义函数时每条名ing默认要加;以表示一条命令的结束 $ add 1 3 4 #定义在多行的情况 $ function mul { #以这种方式定义就如同在脚本里直接写一样 > echo $[ $1 * $2 ] > } $ mul 1 2 2方法二:直接在命令行上用source导入函数库
$ . funcs.sh $ div 5 0 Divide by zero!
注意!以上两种方法中,如果定义的函数和内部命令名相同会覆盖内部命令,但不过在退出终端后这些函数将失效!
方法三:在bash启动文件.bashrc中定义函数,这样就可以当做内部命令使用,并且是永久有效的,.bashrc是bash的配置文件,位于用户主目录下
直接在.bashrc中将函数定义写上去或者使用source命令将函数库导入到.bashrc文件中,这样就可以在命令行上把这些函数当做内部命令来使,因为和内部命令是平起平坐的,因此也可以在任何脚本中像使用ls命令一般直接使用这些函数。
注意!修改后需要重新启动终端才能真正起作用。
9. 递归:
#!/bin/bash #一个求阶乘的经典例子 function fac { if [ $1 -eq 1 ] then echo 1 else echo $[ $1 * `fac $[ $1 - 1 ]`] #所有语言的递归函数都是大同小异的 fi } while read -p "Please input a number: " n [ $n -ne 0 ] do echo `fac $n` done
10. 可变数组:
#!/bin/bash arr=(one two three four five) #使用圆括号和空格分隔符来定义数组(学名叫可变数组) echo $arr #显示第一个元素 echo ${arr[2]} #显示2号元素,索引从0开始,宏替换的时候需要下标,因此为${arr[index]} #因为arr[2]这整个整体作为一个完整的宏,如果直接$arr[2]则会输出one[2] echo ${arr[*]} #显示所有元素 for x in ${arr[*]} #逐个解析数组元素 do echo $x done arr[2]=kkkk echo ${arr[2]} echo ${arr[*]} unset arr[2] #删除相应下标的元素 echo ${arr[*]} #看上去好像是真的删除了 echo ${arr[2]} #实际上是将arr[2]置成NULL了,并没有将这个位置也删除掉 #因此命令unset只能将数组中某个位置的元素设成NULL echo ${arr[10000]} #正向越界返回NULL echo ${arr[-1]} #反向越界直接报错
11. 和函数之间传递可变数组的问题:
将数组传入函数并在函数中当做数组使用:
#!/bin/bash function prc { #由于传进去的是一个一个参数,这和普通命令行传参没两样,因此要在函数中使用数组则必须将一个个参数重构成一个新的数组 local arr=(`echo "$@"`) #先获得参数列表(参数使用空格分开的),然后再用()运算符构造一个新的数组 echo The new arrary is ${arr[*]} #这样就可以通过下标访问了 echo arr[2] is ${arr[2]} echo -n "and sum is " local sum=0 for (( i = 0; i < $#; i++ )) do sum=$[ $sum + ${arr[$i]}] done echo $sum echo -n "also can be " sum=0 for x in "$@" do sum=$[ $sum + $x ] done echo $sum } arr=(1 2 3 4 5 6) prc ${arr[*]} #传进去的时候只能将数组元素分解成一个个参数穿进去,而不能直接穿一个$arr,这表示只传第一个元素进去从函数中返回数组:
相关文章推荐
- 【Shell 编程基础第二部分】Shell里的流程控制、Shell里的函数及脚本调试方法!
- 第10课shell脚本基础3-函数及常用命令
- SHELL基础二函数和字符
- shell(1):shell基础及函数,字符串,if,while,时间处理等应用
- 【类unix系统shell基础】1.09命令组与函数
- Linux新手生存笔记[10]——shell脚本基础3-函数及常用命令
- Linux基础-shell脚本知识整理和脚本编写----------变量、运算符、流程控制、函数、计划任务(发送邮件)
- SHELL基础二函数和字符
- SHELL基础二函数和字符
- 【Linux 系统编程】shell 脚本基础学习之函数(五)
- Linux新手生存笔记[10]——shell脚本基础3-函数及常用命令
- Shell中函数基础语法
- 【Shell 编程基础第二部分】Shell里的流程控制、Shell里的函数及脚本调试方法!
- SHELL基础二函数和字符
- SHELL基础二函数和字符
- 【Shell 编程基础第二部分】Shell里的流程控制\函数及\脚本调试
- shell基础篇(九)函数
- SHELL基础二函数和字符
- shell基础之四:函数、死循环及for,while特殊用法
- 【Shell 编程基础第二部分】Shell里的流程控制、Shell里的函数及脚本调试方法