Shell编程基础:函数
Posted gymumanalvin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shell编程基础:函数相关的知识,希望对你有一定的参考价值。
本博文目录索引
[TOC]
一、认识函数
(一)什么是函数?
1、函数,英文名叫:function
2、函数是由若干shell命令组成的语句块
(二)为什么要使用函数?
1、实现代码复用,节省大量重复的代码块
2、实现模块化编程,不同的功能模块之间相对独立,有利于Shell语句块的bug调试和功能更新
(三)函数与Shell脚本的关系
1、函数一般放在Shell脚本中,属于Shell脚本的一部分
2、函数不能独立运行,需要在Shell脚本中调用运行
3、Shell脚本运行时会创建一个Bash子进程,被调用的函数运行在这个子进程中
(四)关于函数理解的误区
1、函数不能单独运行,必须被调用运行
2、函数被调用运行时,无法开启子进程,只能运行在当前Bash进程中
3、函数被调用运行时,可以使用当前Bash进程的普通变量和全局变量,并且可以对它们进行重新赋值、或者取消赋值
二、定义函数
(一)函数的组成结构
函数由两部分组成:函数名和函数体
1、函数名
(1)函数的名字,通用写法是:func_name
(2)在Shell脚本中调用函数时需要用到函数名
(3)函数名的命名必须遵守命名规范!
2、函数体
(1)函数的主体,即由若干shell命令组成的语句块
(2)语句块使用一对花括号 { } 包含起来,语句块与花括号之间必须用空格隔开!
(二)函数名命名规范
1、建议的函数名命名标准:func_ + 驼峰法
- 小驼峰:func_namingNotation
- 大驼峰:func_NamingNotation
2、警告: 为了避免函数名与命令名冲突,不建议把内部命令名、外部命令名、命令别名当作函数名的命名!!!
(三)函数定义的语法格式
1、第一种语法格式
func_name(){
...函数体...
}
2、第二种语法格式
function func_name{
...函数体...
}
3、第三种语法格式
function func_name(){
...函数体...
}
三、函数使用
(一)函数的三种使用方式
1、可在交互式环境下定义函数
2、可将函数放在脚本文件中,作为脚本文件的一部分
3、可放在只包含函数的单独文件中
(二)交互式环境定义和使用函数
[[email protected] ~]# #在交互式环境下定义函数
[[email protected] ~]#func_dir(){
[[email protected] ~]> ls -l
[[email protected] ~]> }
[[email protected] ~]# #在交互式环境下调用函数
[[email protected] ~]#func_dir
1、在交互式环境下,可以通过输入 左花括号{ 触发多行重定向,在多行重定向中输入代码块,然后以 右花括号} 结束多行重定向的方式,定义func_dir函数
2、定义该函数之后,在交互式环境下,可以通过函数名func_dir调用运行此函数,执行效果相当于直接执行 ls -l
3、定义该函数之后,该函数会在当前Bash进程退出前一直保留
4、当前Bash进程退出时,该函数立即失效
5、也可以在当前Bash进程中运行 unset 命令,使该函数立即失效
[[email protected] ~]# #在交互式环境下取消函数
[[email protected] ~]#unset func_dir
(三)在脚本中定义及使用函数
#!/bin/bash
#fileName:func_test.sh
#在脚本中定义函数
func_helloWorld(){
echo "Hello World!";
echo "Today is `date +%F`";
}
#在脚本中调用函数
func_helloWorld;
执行效果:在标准输出打印以下两行信息
Hello World!
Today is 2018-05-10
1、注意:函数必须 先定义、再调用!
2、函数定义代码块必须放在脚本开始部分,函数调用必须在函数定义代码块之后
3、调用函数时仅使用该函数名即可
4、该函数的有效期为此脚本创建的Bash子进程的生命期,该Bash子进程一旦结束退出,该函数立刻失效
(四)使用函数文件
1、为什么要使用函数文件?
(1)可以将经常使用的函数存入函数文件,然后通过函数文件载入Shell的方式,实现函数复用
(2)函数文件名建议与相关任务有某种联系
举例:用来获取本机eth0网卡的IPv4地址
functions.showIP
2、创建函数文件
#!/bin/bash
#fileName:functions.showIP
#在函数文件中定义函数
showIP(){
#用来获取本机eth0网卡的IPv4地址,CentOS6和CentOS7通用!
ip a | grep -A 2 "^2:"|tail -n 1 | sed -r ‘s/.* ([1-9].*)\/.*/\1/‘;
}
注意:函数文件名是functions.showIP,函数名是showIP
(1)函数文件的书写格式和Shell脚本的书写格式是一样的,但是函数文件中主要是存放函数定义
(2)函数文件一般是普通的文本文件,不带有可执行属性
3、将函数文件载入Shell进程
(1)在交互式环境下将函数文件载入当前Bash进程
[[email protected] ~]# #在交互式环境下将函数文件载入当前Bash进程
[[email protected] ~]#source ./functions.showIP
[[email protected] ~]# #在交互式环境下调用函数文件中的函数showIP
[[email protected] ~]#showIP
执行效果:在标准输出打印本机eth0网卡的IPv4地址
172.20.43.100
(2)在脚本中将函数文件载入当前脚本创建的Bash子进程
#!/bin/bash
#fileName:test_showIP.sh
#在脚本中将函数文件载入当前脚本创建的Bash子进程
source ./functions.showIP;
#在当前脚本创建的Bash子进程中调用函数文件中的函数showIP
showIP;
执行效果:在标准输出打印本机eth0网卡的IPv4地址
172.20.43.100
(3)载入函数文件的语法格式
第一种语法格式:
source /PATH/fileName
<source><空格><文件名>
第二种语法格式:
. /PATH/fileName
<点><空格><文件名>
(4)注意事项
这里的文件名要带正确的路径,可以使用绝对路径或相对路径
4、检查函数是否已载入当前Bash进程
[[email protected] ~]#在交互式环境下查看当前Bash进程已经载入的所有函数
[[email protected] ~]#set
执行效果:在标准输出打印当前Bash进程已经载入的所有函数
[此处省略输出信息]
5、删除已经载入当前Bash进程的函数
在对函数定义做过修改之后,需要先删除已经载入当前Bash进程,使其对当前Bash进程不可用
[[email protected] ~]# #删除已经载入当前Bash进程的函数showIP
[[email protected] ~]#unset showIP
命令格式:
unset func_name
6、环境函数
(1)默认情况下定义的函数只在当前Bash进程有效,无法传递给当前Bash进程的子进程,这种函数叫做 普通函数
(2)可以借助export使得函数可以在当前Bash进程及其子进程有效,这种函数叫做 环境函数
(3)注意: 函数必须先定义,然后才能被export声明为环境函数!环境函数的定义和声明无法合并!!!
[[email protected] ~]# #声明环境函数
[[email protected] ~]#export -f showIP
命令格式:
export -f func_name
[[email protected] ~]# #只查看当前Bash进程已经声明的环境函数
[[email protected] ~]#export -f
[[email protected] ~]#declare -xf
注意:
set 是查看当前Bash进程生效的所有函数
export -f 或者 declare -xf 只查看当前Bash进程已经声明的环境函数
四、函数成员
(一)函数参数
1、回顾:shell中常见的参数和特殊变量
参数名/特殊变量名 | 表达的含义 |
---|---|
$1 | 第一个位置参数 |
$2 | 第二个位置参数 |
[email protected] | 位置参数列表当成一个整体 |
$* | 位置参数列表成员彼此独立 |
$# | 位置参数的个数 |
2、传递参数给函数
调用函数时,在函数名后面以空白分割给定参数列表即可
#!/bin/bash
#fileName:test_argsList4Func.sh
#在脚本中定义函数
func_argsList4Func(){
#获取位置参数列表
echo $#;
}
#在脚本中调用函数
func_argsList4Func;
[[email protected] ~]# #把参数列表传递给脚本中的函数
[[email protected] ~]#bash ./test_argsList4Func.sh a b c;
执行效果:在标准输出打印位置参数的个数
3
(二)函数变量
1、函数内部的三种变量
(1)普通变量
(2)环境变量
(3)本地变量
2、普通变量
(1)在函数体中以默认形式定义的变量,都是普通变量
(2)普通变量的作用范围 仅当前Shell进程有效
(3)当当前Shell进程结束退出时,普通变量会被自动销毁
3、环境变量
(1)在函数体中使用 export 声明的变量,就是环境变量
命令格式:
export NAME=VALUE
(2)环境变量的作用范围是 当前Shell进程及其Shell子进程
(3)只有当当前Shell进程及其Shell子进程全部结束退出时,环境变量才会被销毁
4、本地变量
(1)在函数体中使用 local 声明的变量,就是本地变量
命令格式:
local NAME=VALUE
(2)本地变量 仅在所在函数体中有效,无法越过函数体影响当前Shell进程
(3)当函数调用结束时,本地变量会自动被销毁
(三)函数返回值
1、函数的两种返回值
(1)函数的执行结果返回值
(2)函数的退出状态码
2、函数的执行结果返回值
(1)函数体内部使用echo等命令,执行结果当作返回值输出
#!/bin/bash
#fileName:test_echoReturnValue.sh
#在脚本中定义普通函数
func_echoReturnValue(){
#使用echo命令
echo Hello World!;
}
#在脚本中调用普通函数
func_echoReturnValue;
[[email protected] ~]# #在当前Bash进程的Bash子进程中运行脚本
[[email protected] ~]#bash ./test_echoReturnValue.sh
执行效果:在标准输出打印一行信息
Hello World!
(2)函数体内部调用命令,执行结果当作返回值输出
#!/bin/bash
#fileName:test_showIPReturnValue.sh
#在脚本中定义普通函数
func_showIPReturnValue(){
#调用ip命令
ip a | grep -A 2 "^2:"|tail -n 1 | sed -r ‘s/.* ([1-9].*)\/.*/\1/‘;
}
#在脚本中调用普通函数
func_showIPReturnValue;
[[email protected] ~]# #在当前Bash进程的Bash子进程中运行脚本
[[email protected] ~]#bash ./test_showIPReturnValue.sh
执行效果:在标准输出打印本机eth0网卡的IPv4地址
172.20.43.100
3、函数的退出状态码
(1)默认取决于函数中执行的最后一条命令的退出状态码
#!/bin/bash
#fileName:test_defaultReturnValue.sh
#在脚本中定义普通函数
func_defaultReturnValue(){
#调用true命令,没有任何标准输出,只有退出状态码为0
true;
}
#在脚本中调用普通函数
func_defaultReturnValue;
#查看函数中执行的最后一条命令的退出状态码
echo $?;
[[email protected] ~]# #开启Bash子进程运行包含函数调用的脚本
[[email protected] ~]#bash ./test_defaultReturnValue.sh
执行效果:在标准输出打印一行信息
0
(2)自定义退出状态码
#!/bin/bash
#fileName:test_assignReturnValue.sh
#在脚本中定义普通函数
func_assignReturnValue(){
#指定退出状态码为255
return 255;
}
#在脚本中调用普通函数
func_assignReturnValue;
#查看函数中的自定义退出状态码
echo $?;
[[email protected] ~]# #开启Bash子进程运行包含函数调用的脚本
[[email protected] ~]#bash ./test_assignReturnValue.sh
执行效果:在标准输出打印一行信息
255
-EOF-
以上是关于Shell编程基础:函数的主要内容,如果未能解决你的问题,请参考以下文章