声明

方式1

function func {
        echo 'hi'
        echo 'hello'
}

声明函数名为func的函数,注意这里的函数名之后必须接空格,再加上大括号

方式2

func(){
        echo 'hi'
        echo 'hello'
}

func为函数名,括号与大括号之间不需要空格

使用

#!/bin/bash
func(){
	echo 'Hello'
}
func
#Hello
  • 函数名必须唯一
  • 先声明,再使用

返回值

退出码

#输出上一条命令的状态码
echo $?

状 态 码

描 述

0

命令成功结束

1

一般性未知错误

2

不适合的shell命令

126

命令不可执行

127

没找到命令

128

无效的退出参数

128+x

与Linux信号x相关的严重错误

255

正常范围之外的退出状态码

130

通过Ctrl+C终止的命令

$?保存上个已执行命令的退出状态码 , 注意这里时上一条命令,对于function中包含多个命令也是返回function中最后一条命令的状态码

退出码不意味着函数执行成功,默认情况下,以最后一条命令的退出码作为函数的退出码

#!/bin/bash
func(){
	ls -l /a
	echo 'Hello'
}
func
echo $?

Hello
0

ls: cannot access '/a': No such file or directory

使用return

#!/bin/bash
func(){
	echo 'Hello'
	return 6
}
func
echo $?

6

return可以指定函数的退出状态码,但必须是0~255。

return 与 $? 之间不能再调用其他命令,否则还是返回最后一此执行命令的退出码

不能返回字符串

#!/bin/bash
func(){
	echo 'Hello'
	return 'hello'
}
func
echo $?

Hello
2

script.sh: line 4: return: hello: numeric argument required

echo

#!/bin/bash
func(){
	echo 'Hello'
}
if [[ `func` = 'Hello' ]]
then 
	echo 'true'
else 
	echo 'false'
fi
echo $(func)

true
Hello

这里使用echo以及反引号(或$括号)将函数运行结果赋值给变量

这里最好只有一个echo ,否则比较结果时会不相等

#!/bin/bash
func(){
	echo 'hi'
	echo 'Hello'
}
if [[ `func` = "hi Hello" ]]
then 
	echo 'true'
else 
	echo 'false'
fi
echo $(func)

函数的参数

#!/bin/bash

add() {
	echo $#
	echo $[ $1 + $2 ]
}
add 1 4 3

$#获取参数的个数,$+索引(从1开始) 获得指定索引参数值

函数变量作用域

全局变量

#!/bin/bash

func1(){
 temp=10
}
temp=0

func1

echo $temp
#10

可以看到全局变量temp被函数内部修改了,这样可能导致很多意想不到的后果

#!/bin/bash

func1(){
 temp=10
}


func1

echo $temp
# 10

这个例子更能说明,函数内部声明的变量,外部也可以访问。所以函数内部的变量最好加上local

局部变量:local关键字

#!/bin/bash

func1(){
 local temp=10
}
temp=0

func1

echo $temp
# 0

这里输出的temp依然为0,local关键字保证了变量只局限在该函数中

数组参数

#!/bin/bash

func1(){
 local tempArr=$1
 echo ${tempArr[*]}
}

arr=(20 2 3 4 5)
func1 $arr

# 20

将数组变量作为函数参数,函数只会取数组变量的第一个值。

#!/bin/bash
# array variable to function test
function arrTest {
	local newarray
	#$@将所有变量拼成字符串,$()将命令结果赋值给变量,()括号重新组合为数组
	newarray=($(echo "$@"))
	echo $newarray
	echo "The new array value is: ${newarray[*]}"
}
myarray=(1 2 3 4 5)
arrTest ${myarray[*]}
arrTest $myarray

# 1
# The new array value is: 1 2 3 4 5

# 1
# The new array value is: 1

$@将所有变量拼成字符串,$()将命令结果赋值给变量,()括号重新组合为数组

返回数组

#!/bin/bash

function arrTest {
	local newarray
	newarray=(1 2 3 30)
	echo ${newarray[*]}
}
newArr=`arrTest`
echo $newArr
twoArr=(`arrTest`)
echo $twoArr

#1 2 3 30
#1

递归

#!/bin/bash

function resc {
	
	if [ $1 -eq 1 ]
	then 
	 echo 1
	else
	 local temp=$[$1-1]
	 local res=`resc $temp`
	 echo $[ $res * $1 ]
	fi
}
result=`resc 5`
echo $result

库文件

定义库文件

#文件名为test
function addem {
    echo $[ $1 + $2 ]
}

使用库文件

#! /bin/bash

. ./test

result=$(addem 10 15)

echo $result

注意:

  • 这里的库文件,并没有#! /bin/bash
  • shell函数的作用域上,和环境变量一样, shell函数仅在定义它的shell会话内有效 。如果你在shell命令行界面的提示符下运行test shell脚本, shell会创建一个新的shell并在其中运行这个脚本。 而其他脚本无法使用。
  • 这同样适用于脚本。如果你尝试像普通脚本文件那样运行库文件,函数并不会出现在脚本中。
  • 使用函数库的关键在于source命令。 source命令会在当前shell上下文中执行命令,而不是
    创建一个新shell。可以用source命令来在shell脚本中运行库文件脚本。这样脚本就可以使用库
    中的函数了。
  • source命令有个快捷的别名,称作点操作符( dot operator)。要在shell脚本中运行myfuncs
    库文件,只需添加下面这行: . ./test 。注意后面为脚本访问库文件的相对路径

命令行上创建函数

  • 一种方法是采用单行方式定义函数。 当在命令行上定义函数时,你必须记得在每个命令后面加个分号,这样shell就能知道在哪里是命令的起止了。
[root@localhost monitor]# function divem { echo $[ $1 / $2 ]; }
[root@localhost monitor]# divem 100 10
10
  • 另一种方法是采用多行方式来定义函数。在定义时, bash shell会使用次提示符来提示输入更多命令。用这种方法,你不用在每条命令的末尾放一个分号,只要按下回车键就行。 在函数的尾部使用花括号, shell就会知道你已经完成了函数的定义。
[root@localhost monitor]# function multem {
> echo $[ $1 + $2 ]
> }
[root@localhost monitor]# multem 20 30
50

.bashrc

bash shell在每次启动时都会在主目录/root下查找.bashrc文件

# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
	. /etc/bashrc
fi
##bashrc文件中新增addem函数
addem(){
    echo $[ $1+$2 ]
}

在.bashrc文件中新增addem函数,则在任意位置打开的shell命令窗口都可以直接使用该函数

也可以使用source命令在.bashrc文件中,指定需要增加的库文件路径

shell还会将定义好的函数传给子shell进程,这些函数就自动能够用于该shell会话中的任何shell脚本了 。ps:实际测试中发现用不了,原因未知。