Shell函数是一组命令集或语句组成一个可用块。利用函数可以简化脚本编写。函数要求先定义再使用,调用函数时直接使用函数名即可。这里主要介绍shell编程中函数定义、调用、获取函数参数以及获取函数返回值等内容。

函数定义

函数由函数名和函数体两部分组成。形式如下:

function_name()
{
程序段
}

也可以在函数名前面加上function关键字。如下

function function_name()
{
程序段
}

下面我们看一个shell函数最简单的实例,打印指定输出内容:

print_msg() <-- 定义函数,函数名为print_msg
{
echo "Hello World" <-- 函数体
}

这里,print_msg就是函数名,echo行就是函数体。函数定义就是这样子,那么如何调用函数呢?就是通过使用函数名+参数的方法进行函数调用。函数调用语法如下:

function_name [para1] [para2] ... [paraN]

由于print_msg()函数不需要参数,所以调用形式如下:

#!/bin/bash

print_msg() #定义函数,函数名为print_msg
{
echo "Hello World" #函数体
}
print_msg #调用print_msg函数

到这里,函数的定义和函数调用方法就介绍完了。但是如果你想要函数打印你指定输出内容呢?这时就需要考虑向函数传递指定参数了。

向函数传递参数

我们先将上述指定输出固定内容的print_msg函数进行扩展,实现按照指定内容输出的函数。代码如下:

#!/bin/bash

print_msg()  # 定义函数,函数名为prompt_msg
{
msg_level=$ # 获取函数输入的第一个参数,赋值给变量msg_level
msg_info=$ #获取函数输入的第二个参数,赋值给变量msg_info echo "${msg_level}: ${msg_info}"
} print_msg "ERROR" "The Directory not exist" #使用函数名prompt_msg调用函数,向函数传递2个参数,分别为"Error"、"The Directory not exist"

这里,我们注意到函数体中出现了$1、$2的特殊字符。这代表什么含义?这里也是本章节想要描述的主要内容。下面我们看下函数中常用的类似$1、$2的特殊字符以及它们的含义和使用方法。

$0:表示调用的脚本名。

 $1、$2、$3...$n:表示传入函数的第1个参数、第2个参数、第3个参数...第n个参数。

$#:表示传入参数个数的总数。

 $@:表示"$1"、"$2"、"$3"..."$n",每个变量都是独立的,常用。

 $*:表示"$1 $2 $3...$n",每个变量不是独立的。如果以$*作为传参相当于就只有1个参数。

说明:$@要比$*用的多,因为$*将所有的参数当做单个字符串,因此它很少被使用。

下面我们就针对$0、$1、$#、$@、$*等特殊符号进行逐一介绍。利用这些符号,我们继续完善上述的例子。

#!/bin/bash

print_msg()  #定义函数,函数名为prompt_msg
{
if [ $# -ne ];then # $#表示传入参数总数,即如果参数总数不等于2,则函数报错退出
echo "$0" #输出函数名
echo "$@" # $#输出所有传入函数的参数
echo "please input 2 parameters,please check"
exit
fi msg_level=$ #获取函数输入的第一个参数,赋值给变量msg_level
msg_info=$ #获取函数输入的第二个参数,赋值给变量msg_info echo "${msg_level}: ${msg_info}"
} print_msg "Para1" "Para2" "Para3" # 使用函数名prompt_msg调用函数,输入"Para1" "Para2" "Para3" 3个参数

输出结果如下:

./print_msg.sh #$ 脚本名
Para1 Para2 Para3 # $@
please input parameters,please check

从输出结果应该知道$0、$#、$@表示的含义了。那$@和$*在使用上有什么区别呢?我们通过2个实例来看下,假设脚本名称为script.sh。代码如下

#!/bin/bash

main()
{
echo "Parameter number: $#"
echo "Parameter Value: $@"
} main $@

调用脚本为:script.sh 'Hello' 'World',输出结果如下

Parameter number:
Parameter Value: Hello World

说明:main $@就相当于main ‘Hello’ ‘World’,独立的输入传入脚本的参数。

使用函数返回值

通常使用函数完成一段逻辑处理或者判断函数返回状态完成下一步处理。函数返回值通常有2种形式:(1)使用return语句返回某个数值(0~255),0通常用于表示正确处理无错误返回,非0表示处理异常返回。(2)使用echo返回指定字符串,然后调用程序将函数的执行结果赋值给指定变量。

(1)使用return返回数值的使用方法。下面我们通过一个判断是否为奇数的函数来先了解下,代码如下:

#!/bin/bash

is_odd()
{
num=$
if [ $(expr $num % ) -ne ];then
return
else
return
fi
} number=
is_odd "${number}"
if [ $? -eq ];then # $?表示上一条命令执行返回的。
echo "$number is odd"
else
echo "$number is not odd"
fi

说明:is_odd函数使用return语句返回判断结果。下一个命令通过$?获取函数的输出返回值进行判断。记住$?的使用方法,非常常用。

(2)使用echo返回字符串的方法,下面我们通过一个简单的例子来看下。

#!/bin/bash

fun()
{
echo "Hello World"
} Str=$(fun)
echo $Str

函数利用echo返回"Hello Word"字符串,脚本再通过变量Str去获取即可。就是这么使用。

函数变量和脚本变量

所谓的脚本变量就是不在函数内定义的变量。使用函数变量和脚本变量主要关注其作用域。二者的作用域不同,主要区别如下:

(1)脚本变量是全局的,作用域是从变量定义到脚本结束。

#!/bin/bash

func()
{
echo $num #输出100
num= # 修改变量num值为200
}
num=
func # 调用函数,num值修改为200
echo $num # 输出200

(2)函数变量定义的变量默认也是全局的,但是作用域是从函数被调用时执行变量定义开始到脚本结束。

#!/bin/bash

func()
{
num= # 定义函数变量num,默认属性是全局。
} func
echo $num # 输出200

(3)如果函数变量前带关键字local,则函数变量作用域仅局限于函数内。

#!/bin/bash

func()
{
local num= # 带关键字local,定义函数变量num。num变量作用域为函数内。
echo $num # 输出200
} num=
func
echo $num # 输出100,变量值未改变。如果把num=100的定义去掉,这里会显示为空,原因是变量未定义。

看了这3个例子,应该清楚函数变量和脚本变量的作用域区别。在shell编程中,建议在函数中定义变量全部带关键字local,否则容易出现全局变量被修改而导致程序执行错误。

参数变量偏移shift

参数变量偏移shift用的比较少,但是不代表不需要会用,某些使用利用shift可以很快速的完成指定的需求。刚开始学习shell编程的时候一直不太理解这个shift关键字有什么作用,也不知道在哪些场景下可以使用,后来在阅读别人的代码和实践中才发现其妙处。下面我们先看例子,通过例子再介绍它的使用方法。假设脚本名为script.sh,脚本调用传参为script.sh "add" "100" "200" "300"

#!/bin/bash

add()
{
echo "$1+$2+$3"|bc
} multiply()
{
echo "$1*$2*$3"|bc
} if [ $ == "add" ];then
echo "$@" <-- 打印脚本传入的所有参数,输出add
shift <-- 偏移第1个参数
echo "$@" <-- 打印便宜后的参数,输出100
add $@ <-- 获取相加的值,输出600
else
shift
multiply $@
fi

看结果应该知道shift用法了吧。shift会移动参数变量,而且shift后面可以接数字,代表跳过前面几个参数。也就是当你脚本考虑跳过某些参数时,就可以使用shift关键字了。

总结

使用函数可以节省大量的脚本编写时间,也可以使脚本结构更加清晰。对于经常使用到的逻辑语句可以整理成函数保存到文件中,可以方便后续脚本编写。

Shell函数使用方法的更多相关文章

  1. shell 从函数文件中调用函数的方法

    你可以把所有的函数存储在一个函数文件中 你可以把所有的文件函数加载到当前脚本或命令行 加载函数文件中所有函数的方法: source xxx.sh

  2. Shell入门教程:Shell函数详解

    Shell函数类似于Shell脚本,里面存放了一系列的指令,不过Shell的函数存在于内存,而不是硬盘文件,所以速度很快,另外,Shell还能对函数进行预处理,所以函数的启动比脚本更快. 1.函数定义 ...

  3. Shell入门教程:Shell函数的返回值

    shell函数返回值一般有3种方式: 1.return语句(默认的返回值) shell函数的返回值可以和其他语言的返回值一样,通过return语句返回. 比如: #!/bin/bash functio ...

  4. (转)Shell函数

    Shell函数类似于Shell脚本,里面存放了一系列的指令,不过Shell的函数存在于内存,而不是硬盘文件,所以速度很快,另外,Shell还能对函数进行预处理,所以函数的启动比脚本更快. 1.  函数 ...

  5. Linux Shell系列教程之(十五) Shell函数简介

    本文是Linux Shell系列教程的第(十五)篇,更多Linux Shell教程请看:Linux Shell系列教程 函数可以将一个复杂功能划分成若干模块,从而使程序结构更加清晰,代码重复利用率更高 ...

  6. Shell函数的简单应用

    Shell函数的简单应用 在脚本内给函数传参: #!/bin/bash . /etc/init.d/functions CheckUrl (){ curl -I -s $ | head - } Che ...

  7. Shell函数语法

    Shell函数语法 定义函数: function   函数名(){ 指令... } 调用函数,方法1: 函数名 调用函数,方法2: 函数名  参数一   参数二 return在函数里面使用会跳出函数并 ...

  8. python基础:os模块中关于文件/目录常用的函数使用方法

    Python是跨平台的语言,也即是说同样的源代码在不同的操作系统不需要修改就可以同样实现 因此Python的作者就倒腾了OS模块这么一个玩意儿出来,有了OS模块,我们不需要关心什么操作系统下使用什么模 ...

  9. os模块中关于文件/目录常用的函数使用方法

    os模块中关于文件/目录常用的函数使用方法 函数名 使用方法 getcwd() 返回当前工作目录 chdir(path) 改变工作目录 listdir(path='.') 列举指定目录中的文件名('. ...

随机推荐

  1. 报错:Column count doesn't match value count at row 1

    mysql错误:Column count doesn't match value count at row 1 意思是存储的数据与数据库表的字段类型定义不相匹配. 解决办法:检查段类型是否正确, 是否 ...

  2. C/C++ 与 Python 的通信

    作者:Jerry Jho链接:https://www.zhihu.com/question/23003213/answer/56121859来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...

  3. DOM内容操作和自定义、样式改变

    自定义 function 方法名或函数名(参数1,参数2,...) { 方法体: return返回值:(可不写) } function abc() { alert("123"); ...

  4. (转) C#之VS自带RDLC报表学习

    原文地址:http://blog.csdn.net/hk_5788/article/details/49846905  原文工具VS2010,测试版本工具VS2013 报表是这样设计的: 看看结果: ...

  5. Ren'Py视觉小说安装,玩一下吧,上班很闲的话

    ---------------------------------------------------------------------------------------------------- ...

  6. underscore函数存在两种用法

    var _ = require('underscore'); var a = {"a": 1, "b": 2}; console.log(_(a).size() ...

  7. Nginx的安装(CentOS 7环境)

    安装所需环境 Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Windows 版本,本篇则使用 CentOS 7 作为安装环境. 一. gcc 安装安装 nginx 需要先 ...

  8. redis集群尝试

    1. 使用Docker搭建redis主从复制集群 安装参照 Docker 搭建redis 集群 启动服务 docker run --name redis-master -p 6379:6379 -d ...

  9. python3封装Api接口

    注:本篇的代码和语法基于Python3.5环境,下面将用到Python 的Flask框架 封装接口主要讲静态接口(无参数传入).动态接口(有参数传入,不同参数返回的信息不同).针对动态接口有三种传参方 ...

  10. 6.简单提取小红书app数据(简单初步试采集与分析)-1

    采集小红书数据爬虫:1.本来是要通过app端的接口去直接采集数据,但是app接口手机端设置本地代理这边开启抓包后就不能正常访问数据.所以就采用了微信小程序里的小红书app接口去采集数据. 2.通过 f ...