bash shell笔记7 创建函数

原创 2013年12月02日 09:13:39
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://twentyfour.blog.51cto.com/945260/525126

知识体系:
#创建函数
#使用参数
#共享函数
shell脚本代码可以封装在函数内,而函数可以在脚本任意处使用,由此减少大段代码的重复编写。

1、基本脚本函数
函数是被赋予名称的脚本代码块,可以在代码的任意位置使用。当需要调用代码块的时候,只需引用代码块被赋予的函数名即可。
1.1、创建函数
在bash shell脚本中创建函数可以使用两种方式:
*关键字function,基本格式为:
function name{
  commands
}
*()方式:
name() {
  commands
}
下面就对这两种方式举例创建.
1.2、使用函数
如下采用上面创建函数的两种方式举例:
[root@wzp ~]# chmod u+x 7.1test 
[root@wzp ~]# cat 7.1test 
#!/bin/bash
function fun1 {
  echo  "this is the first function"
}
fun1
fun2() {
  echo  "this is the second function"
}
fun2
[root@wzp ~]# ./7.1test 
this is the first function
this is the second function
这里头有两个函数名:fun1和fun2,对应两个函数执行后显示不同结果。
但是有点要注意的是必须先定义好函数,后才能调用,看个例子先:
[root@wzp ~]# cat 7.1test 
#!/bin/bash
function fun1 {
  echo  "this is the first function"
}
fun1
fun2
fun2() {
  echo  "this is the second function"
}
[root@wzp ~]# ./7.1test 
this is the first function
./7.1test: line 6: fun2: command not found
如上我把fun2放置在定义函数fun2之前就调用,shell是不会回头来执行的,所以对于函数fun2就报错了。
并且还要注意每个函数名必须唯一,如果重新定义函数,那么新定义的将取代原先的定义,看例子:
[root@wzp ~]# cat 7.1test 
#!/bin/bash
function fun1 {
  echo  "this is the first function"
}
fun1
fun1() {
  echo  "this is the second function"
}
fun1
[root@wzp ~]# ./7.1test 
this is the first function
this is the second function
例子很简单,效果也看出来了,所以我们最好区分出函数名了。

2、返回值
bash shell将函数看成小型脚本,并以退出状态结束,我们可以通过$?查看三种不同的退出状态,这一点前面已经讲述过了。
2.1、默认退出状态
我们先来看一个例子:
[root@wzp ~]# cat 7.2test 
#!/bin/bash
function fun1 {
  echo  "this is the first function"
  ls -l xx
}
fun1
echo "the exit status is :$?"
[root@wzp ~]# chmod u+x 7.2test 
[root@wzp ~]# ./7.2test 
this is the first function
ls: xx: 没有那个文件或目录
the exit status is :2
我们看到函数的退出状态为2,因为最后一条命令执行出错了。再来看看另外一种情况:
[root@wzp ~]# cat 7.2test 
#!/bin/bash
function fun1 {
  ls -l xx
  echo  "this is the first function"
}
fun1
echo "the exit status is :$?"
[root@wzp ~]# ./7.2test 
ls: xx: 没有那个文件或目录
this is the first function
the exit status is :0
我把函数的两条命令调换位置执行,可以看到第一条报错了,然后退出状态值却是0。从这点我们发现函数的默认退出状态是不可靠的。
2.2、使用return命令
return命令可以使用单个整数值来定义函数退出状态,如下例子:
[root@wzp ~]# cat 7.2test 
#!/bin/bash
function cto {
  read -p "enter a value:" value
  echo "doubling the value"
  return $[ $value * 2 ]
}
cto
echo "the new value is $?"
[root@wzp ~]# ./7.2test 
enter a value:24
doubling the value
the new value is 48
函数cto将变量$value中用户输入的值变成双倍后,使用命令return命令返回结果,然后用$?显示该结果。
2.3、使用函数输出
对于命令输出可以捕获并存放到shell变量中,函数的输出也可以捕获并放到shell变量中,看例子:
[root@wzp ~]# chmod u+x 7.3test 
[root@wzp ~]# cat 7.3test 
#!/bin/bash
ceo () {
 read -p "please input a value:" value
 echo $[ $value * 2 ]
}
result=`ceo`   #注意函数的调用方式
echo "the result is : $result"
[root@wzp ~]# ./7.3test 
please input a value:13
the result is : 26
通过定义函数后,把函数输出赋予给变量,这里使用反引号。

3、在函数中使用变量
如下讲述shell脚本函数内外变量处理方法。
3.1、向函数传递参数
bash shell将函数作为小型脚本处理,函数可以使用标准参数环境变量来表示命令行传递给函数的参数,先看如下例子:
[root@wzp ~]# cat 7.3test 
#!/bin/bash
function cio {
 if [ $# -eq 0 ] || [ $# -gt 2 ]
 then
   echo -1
 elif [ $# -eq 1 ]
 then
   echo $[ $1 + $1 ]
 else
   echo $[ $1 * $2 ]
 fi
}
echo "##############1##############"
echo -n "adding 10 and 15 :"
value=`cio 10 15`
echo $value
echo "##############2##############"
echo -n "adding just one num of 10:"
value=`cio 10`
echo $value
echo "##############3##############"
echo -n "adding no num:"
value=`cio`
echo $value
echo "##############4##############"
echo -n "adding three num 10 20 30 :"
value=`cio 10 20 30`
echo $value
[root@wzp ~]# ./7.3test 
##############1##############
adding 10 and 15 :150
##############2##############
adding just one num of 10:20
##############3##############
adding no num:-1
##############4##############
adding three num 10 20 30 :-1
先通过$#来判断参数个数,然后针对个数的不同执行不同的算术运算。通过把参数数目传递给函数去运算,把运行结果显示出来。
还有点注意的,因为函数为自己的参数值使用专用的参数环境变量,所以函数无法从脚本命令行直接访问脚本参数值,也就是说函数不识别运行脚本时后面附带的参数值。如果要调用,必须在使用函数时手工传递这些数据,我们来看个例子:
[root@wzp ~]# cat 7.3test 
#!/bin/bash
bad () {
  echo $[ $1 + $2 ]
}
if [ $# -eq 2 ]
then
  value=`bad`
  echo "the result is : $value"
else
  echo "please input two parameters"
fi
[root@wzp ~]# ./7.3test 
please input two parameters
[root@wzp ~]# ./7.3test 1 2
./7.3test: line 3: +  : syntax error: operand expected (error token is " ")
the result is : 
之所以函数不认识1和2这两个$1、$2,就是因为函数使用的变量不同于脚本主代码的变量,所以我们必须在使用函数的使用手工附加,改成如下:
[root@wzp ~]# cat 7.3test 
#!/bin/bash
bad () {
  echo $[ $1 + $2 ]
}
if [ $# -eq 2 ]
then
  value=`bad $1 $2`
  echo "the result is : $value"
else
  echo "please input two parameters"
fi
[root@wzp ~]# ./7.3test 
please input two parameters
[root@wzp ~]# ./7.3test 8 16
the result is : 24
哈哈,要的就是这个结果,所以value=`bad $1 $2`是关键语句!!!
3.2、在函数中处理变量
这里要提及一个作用域的概念,表示说变量的可见区域。函数内定义的变量和普通变量有不同的作用域,脚本外部定义的变量要覆盖函数内定义的变量。函数使用两个类型的变量:
*全局变量
*局部变量
1》全局变量
全局变量是shell脚本内处处有效的变量,默认情况下脚本中定义的变量都是全局变量,而默认定义的变量在函数内部也可以正常访问的。例子:
[root@wzp ~]# cat 7.3test 
#!/bin/bash
fun () {
  value=$[ $value * 2 ]
}
  read -p "please input the value:" value
  fun
  echo "the new value is : $value"
[root@wzp ~]# ./7.3test 
please input the value:12
the new value is : 24
对于$value是在函数外部定义的,并且是在外部赋值,当调用给函数fun的时候,该变量在函数中也是有效的,所以这是全局变量的作用体现。
2》局部变量
对于函数内部使用的变量则是局部变量,而在声明变量的时候只要在前面多一个local关键字即可,先看下例子:
[root@wzp ~]# cat 7.3test 
#!/bin/bash
function cfo {
 local temp=$[ $value + 5 ]
 result=$[ $temp + 2 ]
}
temp=8
value=10
cfo
echo "the result is $result"
if [ $temp -gt $value ]
then
 echo "temp is larger"
else
 echo "temp is smaller"
fi
[root@wzp ~]# ./7.3test 
the result is 17
temp is smaller
对于这样的结果,可以分析如下:返回$result的结果是从函数中得到的,那么势必采用函数内部的temp变量,而函数内部的$temp变量赋予值后为15,则显示result的值为15+2=17。这一点没什么好质疑的!但是当temp和result进行大小比较的时候,就直接采用全局变量的值,而跟函数内部定义的temp无关了,这也是local定义内部函数的作用体现了。
这里我们顺便把变量的值取出来看看:
[root@wzp ~]# cat 7.3test 
#!/bin/bash
function cfo {
 local temp=$[ $value + 5 ]
 result=$[ $temp + 2 ]
}
temp=8
value=10
cfo
echo "the result is $result"
if [ $temp -gt $value ]
then
 echo "temp is larger"
 echo "temp=$temp ; result=$result"
else
 echo "temp is smaller"
 echo "temp=$temp ; result=$result"
fi
[root@wzp ~]# ./7.3test 
the result is 17
temp is smaller
temp=8 ; result=17
我只是多加了两个echo "temp=$temp ; result=$result",就为了把temp和result这两个变量显示出来,我们看到,执行函数后,temp的值没变,因为函数中局部定义了temp,所以还是8;可是value的值通过函数运算后是有效生成的,所以附加后是17。

4、创建库
函数在单个脚本中有助于减少代码量,如果多个脚本碰巧使用相同的函数可以通过创建函数的库文件,然后再不同脚本中引用该库文件。所以这种方法,首先要创建公共库文件,如下:
[root@wzp ~]# cat funcs 
function ceo {
  echo $[ $1 + $2 ]
}
function cfo {
  echo $[ $1 * $2 ]
}
接下来把如上库文件调用进脚本文件。然后问题在于如果把这个库文件作为普通脚本文件运行,那么这些函数不会出现在脚本文件中,看如下例:
[root@wzp ~]# chmod u+x funcs 
[root@wzp ~]# chmod u+x 7.41test 
[root@wzp ~]# chmod u+x 7.42test 
[root@wzp ~]# cat 7.41test 
#!/bin/bash
./funcs
result=`ceo 12 24`
echo "the result is $result"
[root@wzp ~]# ./7.41test 
./7.41test: line 3: ceo: command not found
the result is 
可以看到调用库文件失败了,问题就处在于通过./执行库函数是不可行的。
解决办法是通过点符号符在shell脚本中运行库文件脚本,即为source命令,其格式是:
. ./xx  切记:两个点号之间有个空格,否则出错) 把例子修改如下:
[root@wzp ~]# cat 7.41test 
#!/bin/bash
. ./funcs
result=`ceo 12 24`
echo "the result is $result"
[root@wzp ~]# cat 7.42test 
#!/bin/bash
. ./funcs     #这一步相当于添加库
result=`cfo 12 5`
echo "the result is $result"
[root@wzp ~]# ./7.41test 
the result is 36
[root@wzp ~]# ./7.42test 
the result is 60
我们看到了满意的结果,关键在于通过. ./点符号符来使得脚本能以调用库文件的函数,这里头是把脚本文件和库文件放置于同一目录,所以为了确保路径问题的可靠性可使用绝对路径。

5、在命令行使用函数
有时候想直接在命令行下使用函数也是可以的,在命令行下使用函数有两种方法,分别如下:
1、将函数定义在一行命令中:
[root@wzp ~]# function 51cto { echo $[ $1 / $2 ]; }
[root@wzp ~]# 51cto 100 20
5
上面这种方法必须在命令的结尾处加分号,使得shell知道命令在哪里分开。
2、使用多行命令定义函数:
[root@wzp ~]# function 51ceo {
> echo $[ $1 * $2 ]
> }
[root@wzp ~]# 51ceo 3 8
24
通过次提示符输入更多命令,在函数末尾处使用大括号,shell就知道了定义函数结束,这种方法就不用使用分号了。


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Tomcat 7学习笔记之配置Web界面管…

在捣腾Tomcat 7的时候遇到一个问题,很多人对tomcat自带的web管理工具不是很熟悉,因为一直都是手动修改配置文件。这次有点好奇想看看tomcat的web管理界面,因为之前一直用weblogi...

mysql 创建带输入参数的函数

代码部分: CREATE DEFINER=`root`@`%` FUNCTION `useableBox`(`p_CBidHold` VARCHAR(50), `p_skuID` INT, `r_G...

shell 字体颜色

echo -e "\033[32;49;1m [DONE] \033[39;49;0m" 输出结果:   [DONE]  ########################### 文本终端的颜色可...
  • eltaera
  • eltaera
  • 2013年07月08日 16:08
  • 318

Linux Bash shell学习笔记7(for循环)

shell中for循环的基本结构为:   for   arg   in   [list]   do              commands ...   done如果do和for想在同一行,需要这样...
  • vah101
  • vah101
  • 2011年04月21日 10:31
  • 20890

2012-7-25可樂分享美文《A lifelon…

A lifelong career 学习一生的事业 As food is to the body, so is learning to the mind. Our bodies grow and mu...

Windows 7局域网共享设置的解决方…

Win7系统的网络功能比XP有了进一步的增强,使用起来也相对清晰。但是由于做了很多表面优化的工作,使得底层的网络设置对于习惯了XP系统的人来说变得很不适应,其中局域网组建就是一个很大的问题。默认安装系...

wind7 安装IIS教程

一、进入Windows7的控制面板,选择左侧的打开或关闭Windows功能。 二、现在出现了安装Windows功能的选项菜单,注意选择的项目,我们需要手动选择需要的功能,下面这张图片把需要安...

转:assert() 函数用法

原文地址:函数用法">转:assert() 函数用法作者:Lynn     assert宏的原型定义在中,其作用是如果它的条件返回错误,则终止程序执行,原型定义: #include void as...

JavaScript window下面的常用函数…

该文章来自于网络,感谢网友的无私奉献。。。     我们常用的一些函数都是全局对象window下面的。这里将其梳理一下: Timers 计时器 引用 global functions setTim...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:bash shell笔记7 创建函数
举报原因:
原因补充:

(最多只允许输入30个字)