shell浅谈之十函数
转自:http://blog.csdn.net/taiyang1987912/article/details/39583179
一、简介
Linux Shell编
程中也会使用到函数,函数可以把大的命令集合分解成若干较小的任务,也避免重复编写相同的代码。在Shell中,所有的函数定义都是平行的,即不允许在函
数体内再定义其他的函数,但允许函数之间相互调用。函数又涉及到很多基本使用:函数参数调用、函数返回值、局部变量及全局变量、函数间的相互调用和函数递
归调用。
二、详解
1、函数的定义
(1)函数是一串命令的
集合,如果脚本中有重复代码时可以考虑使用函数,在shell中函数的返回值只能为退出状态0或1。应注意函数名在脚本中的唯一。可以在函数名前加上
fuction关键字也可省略。函数体中的命令集合必须含有至少一条命令(函数不允许空命令,与C不同)。
(2)脚本遇
到"hello(){"结构时,知道定义了一个名为hello的函数,而且它会记住hello代表的函数,并执行函数体中的命令,直到出现"}"字符结
束,当执行到单独的行hello时,shell就知道应该去执行刚才定义的函数,执行完毕返回继续执行其他的命令或函数。在shell中不需要申明就可直
接定义函数,但在调用函数前需对它进行定义。如下是shell脚本中循环调用函数的例子:
- #function2.sh
 - #!/bin/bash
 - output()
 - {
 - for(( num1 = 1; num1 <= 5; num1++ ))
 - do
 - echo -n "$num1 "
 - done
 - }
 - let "num2=1"
 - while [ "$num2" -le 5 ]
 - do
 - output
 - echo ""
 - let "num2=num2 + 1"
 - done
 
(3)判断当前目录下存在多少个文件和子目录
- #显示当前目录下文件和目录数
 - #function3.sh
 - #!/bin/bash
 - directory()
 - {
 - let "filenum = 0"
 - let "dirnum = 0"
 - ls
 - echo "" #echo换行
 - for file in $( ls ) #for循环判断当前子目录和文件
 - do
 - if [ -d $file ] #判断为子目录
 - then
 - let "dirnum = dirnum + 1"
 - else #判断为文件
 - let "filenum = filenum + 1"
 - fi
 - done
 - echo "The number of directory is $dirnum"
 - echo "The number of file is $filenum"
 - }
 - directory #在脚本中调用函数
 
2、向函数传递参数
shell中,向函数传递的参数仍然是以位置参数的方式来传递的,而不能传递数组等其他形式变量(与c不同)。利用函数参数的传递实现两数的四则运算。
- #用于实现两数加、减、乘和除四则运算
 - #!/bin/bash
 - count()
 - {
 - if [ $# -ne 3 ] #3个参数,一个运算符两个数值
 - then
 - echo "The number of arguments is not 3! "
 - fi
 - let "s = 0"
 - case $2 in
 - +) #加法
 - let "s = $1 + $3"
 - echo "$1 + $3 = $s";;
 - -) #减法
 - let "s = $1 - $3"
 - echo "$1 - $3 = $s";;
 - \*) #乘法
 - let "s = $1 * $3"
 - echo "$1 * $3 = $s";;
 - \/) #除法-取余,浮点数运算使用bc
 - let "s = $1 / $3"
 - echo "$1 / $3 = $s";;
 - *) #其他
 - echo "What you input is wrong!";;
 - esac
 - }
 - echo "Please type your word: ( e.g. 1 + 1 )"
 - read a b c
 - count $a $b $c
 
3、函数返回值
有时需要函数执行完成后返回特定的值来完成脚本的后续操作。函数通过return返回退出状态,0表示true无错误,非0表示false有错误(与C不同)。
- #根据用户输入显示星期
 - #!/bin/bash
 - show_week()
 - {
 - echo -n "What you input is: "
 - echo "$1"
 - case $1 in
 - 0)
 - echo "Today is Sunday. "
 - return 0;;
 - 1)
 - echo "Today is Monday. "
 - return 0;;
 - 2)
 - echo "Today is Tuesday. "
 - return 0;;
 - 3)
 - echo "Today is Wednesday. "
 - return 0;;
 - 4)
 - echo "Today is Thursday. "
 - return 0;;
 - 5)
 - echo "Today is Friday. "
 - return 0;;
 - 6)
 - echo "Today is Saturday. "
 - return 0;;
 - *)
 - return 1;;
 - esac
 - }
 - #if show_week "$1" #返回0表示函数输入的命令行参数是正确的
 - #也可以通过$?来获取函数执行的返回值
 - show_week "$1"
 - if [ $? -eq 0 ]
 - then
 - echo "What you input is right! "
 - else
 - echo "What you input is wrong! "
 - fi
 - exit 0
 
4、函数调用
shell脚本中可以同时放置多个函数,函数之间允许相互调用,而且允许一个函数调用多个函数。
- #用于显示一个不多于5位的正整数的位数,并按顺序显示各个数位的值
 - #!/bin/bash
 - count_of_int()
 - {
 - if [ $1 -gt 9999 ]
 - then
 - let "place=5" #5位数
 - elif [ $1 -gt 999 ]
 - then
 - let "place=4"
 - elif [ $1 -gt 99 ]
 - then
 - let "place=3"
 - elif [ $1 -gt 9 ]
 - then
 - let "place=2"
 - else
 - let "place=1" #1位数
 - fi
 - echo "The place of the $1 is $place." #整数的位数
 - }
 - num_of_int()
 - {
 - let "ten_thousand = $1/10000" #整数的数位分解值
 - let "thousand =$1/1000%10"
 - let "hundred = $1/100%10"
 - let "ten = $1%100/10"
 - let "indiv = $1%10"
 - if [ $ten_thousand -ne 0 ]
 - then
 - echo "$ten_thousand $thousand $hundred $ten $indiv"
 - elif [ $thousand -ne 0 ]
 - then
 - echo "$thousand $hundred $ten $indiv"
 - elif [ $hundred -ne 0 ]
 - then
 - echo "$hundred $ten $indiv"
 - elif [ $ten -ne 0 ]
 - then
 - echo "$ten $indiv"
 - else
 - echo "$indiv"
 - fi
 - }
 - show()
 - {
 - echo "Please input the number(1-99999): "
 - read num
 - count_of_int $num
 - num_of_int $num
 - }
 - show
 
执行脚本,输入整数2014,该数是四位数,千位是2,百位是0,十位是1,个位是4。
5、函数中局部和全局变量
shell中,可以通过local关键字来申明局部变量,局部变量将局限在函数范围内。函数可调用函数外的全局变量,若一个局部变量和一个全局变量的名字相同,则在函数中局部变量会覆盖掉全局变量。
- #!/bin/bash
 - text="global variable"
 - use_local_var_fun()
 - {
 - local text="local variable" #local声明为局部变量,否则会修改全局text的值
 - echo "in function------"$text #暂时覆盖掉全局变量的值
 - }
 - use_local_var_fun
 - echo "Out of function------"$text #text的值为开始定义的值
 - exit 0
 
6、函数递归
(1)shell中执行递归函数可以直接或间接地反复调用其自身,每调用一层就进入新的一层,主调函数又是被调函数。
(2)使用局部变量进行递归实现阶乘运算,也可采用递推法实现。
- #阶乘运算,当n=0时 0!=1,当n>=1时n!=n*(n-1)!
 - #!/bin/bash
 - fact ()
 - {
 - local num=$1 #函数需将先前的局部值进行逐个还原,故设置成局部的变量
 - echo $num
 - if [ "$num" -eq 0 ]
 - then
 - factorial=1
 - else
 - let "decnum=num-1"
 - fact $decnum
 - let "factorial=$num * $?"
 - fi
 - return $factorial
 - }
 - fact $1
 - echo "Factorial of $1 is $?"
 - exit 0
 
(3)递归实现汉诺塔的问题(不使用局部变量的递归)
- #汉诺塔算法
 - #!/bin/bash
 - move=0
 - dohanoi()
 - {
 - if [ $1 -eq 0 ]
 - then
 - echo ""
 - else
 - dohanoi "$(($1-1))" $2 $4 $3
 - echo "move $2 ----> $3"
 - let "move=move+1"
 - dohanoi "$(($1-1))" $4 $3 $2
 - fi
 - if [ $# -eq 1 ]
 - then
 - if [ "$(( $1 > 1 ))" -eq 1 ]
 - then
 - dohanoi $1 A C B
 - echo "Total moves = $move"
 - else
 - echo "The number of disk which you input is illegal! "
 - fi
 - fi
 - }
 - echo "Please input the num of disk:"
 - read num
 - dohanoi $num 'A' 'B' 'C'
 
三、总结
(1)函数间的相会调用增加了shell编程的灵活性和代码的可重用性,对脚本语言来说很是实用。
(2)函数的递归调用应进一步理解,阶乘和汉诺塔的实现可逐步分析。
(3)通过函数可以封装自己的函数库,减少以后开发的难度并使用代码的可重复性
shell浅谈之十函数的更多相关文章
- shell浅谈之九子shell与进程处理
		
转自:http://blog.csdn.net/taiyang1987912/article/details/39529291 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] ...
 - 浅谈 es6 箭头函数, reduce函数介绍
		
今天来谈一下箭头函数, es6的新特性 首先我们来看下箭头函数长什么样子, let result = (param1, param2) => param1+param2; 上述代码 按照以前书写 ...
 - 浅谈js回调函数
		
回调函数原理: 我现在出发,到了通知你”这是一个异步的流程,“我出发”这个过程中(函数执行),“你”可以去做任何事,“到了”(函数执行完毕)“通知你”(回调)进行之后的流程 例子 1.基本方法 ? 1 ...
 - 浅谈JSON.stringify 函数与toJosn函数和Json.parse函数
		
JSON.stringify 函数 (JavaScript) 语法:JSON.stringify(value [, replacer] [, space]) 将 JavaScript 值转换为 Jav ...
 - 浅谈JavaScript eval() 函数
		
用js的人都应该知道eval()函数吧,虽然该函数用的极少,但它却功能强大,那么问题来了,为什么不常用呢?原因很简单,因为eval()函数是动态的执行其中的字符串,里面有可能是脚本,那么这样的话就有可 ...
 - 浅谈C++虚函数
		
很长时间都没写过博客了,主要是还没有养成思考总结的习惯,今天来一发. 我是重度拖延症患者,本来这篇总结应该是早就应该写下来的. 一.虚函数表 C++虚函数的机制想必大家都清楚了.不清楚的同学请参看各种 ...
 - Qt浅谈之四十九俄罗斯方块(代码来自网络)
		
一.简介 从网上下载了一个Qt实现的俄罗斯方块单机版的源码,觉得非常有意思,故以博客形式记录下来,以便慢慢来研究.在centos6.6下编译运行(注意程序运行需要读取pro目录的配置文件,若把编译目录 ...
 - Qt浅谈之四十五QSplitter实现自由伸缩滑动窗口
		
一.简介 最近看到一篇Qt实现伸缩滑动的窗口的文章,但其代码不完整.便在此重新书写了完整的代码,并开源出来.窗口的中央有滑动条可以动态改变子窗口的大小,隐藏的按钮可以快速伸缩子窗口.其效果图如下: 二 ...
 - 浅谈JavaScript匿名函数与闭包
		
一. 匿名函数 //普通函数定义: //单独的匿名函数是无法运行的.就算运行了,也无法调用,因为没有名称. 如: function(){ alert('123'); ...
 
随机推荐
- OS的沙盒机制 --基础知识
			
/* iOS的沙盒机制,应用只能访问自己应用目录下的文件. iOS不像android,没有SD卡概念,不能直接访问图像.视频等内容. iOS应用产生的内容,如图像.文件.缓存内容等都必须存储在自己的沙 ...
 - 了解HTML CSS格式化排版 文字排版
			
这里简单的写一些涉及到字体排版中常用到的属性, 大家可以学习查看, 也可以mark下以后看. font-family: "Micrsoft Yahei"; 设置字体 font-si ...
 - 转载:WinForm中播放声音的三种方法
			
转载:WinForm中播放声音的三种方法 金刚 winForm 播放声音 本文是转载的文章.原文出处:http://blog.csdn.net/jijunwu/article/details/4753 ...
 - Linux MySQL源码安装缺少ncurses-devel包
			
在Red Hat Enterprise Linux Server release 5.7 上用源码安装MySQL-5.6.23时,遇到了" remove CMakeCache.txt and ...
 - mysqldump:Couldn't execute 'show create table `tablename`': Table tablename' doesn't exist (1146)
			
遇到了一个错误mysqldump: Couldn't execute 'show create table `CONCURRENCY_ERRORS`': Table INVOICE_OLD.CONCU ...
 - Redhat Linux安装JDK 1.7
			
本篇主要介绍在Redhat Linux(Red Hat Enterprise Linux Server release 5.7 (Tikanga))系统上安装JDK 1.7,其它Linux平台安装也大 ...
 - CPU 和内存虚拟化原理 - 每天5分钟玩转 OpenStack(6)
			
前面我们成功地把 KVM 跑起来了,有了些感性认识,这个对于初学者非常重要.不过还不够,我们多少得了解一些 KVM 的实现机制,这对以后的工作会有帮助. CPU 虚拟化 KVM 的虚拟化是需要 CPU ...
 - [HTML表格]在databases显示行的附加信息
			
模板代码: <!-- DataTables CSS --> <link rel="stylesheet" href="{% static 'DataTa ...
 - [转载]python:open/文件操作
			
open/文件操作f=open('/tmp/hello','w') #open(路径+文件名,读写模式) #读写模式:r只读,r+读写,w新建(会覆盖原有文件),a追加,b二进制文件.常用模式 如:' ...
 - BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】
			
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 7687 Solved: 3516[Subm ...