linux shell 函数

脚本函数基础

创建函数

在 bash shell 脚本中创建函数的语法有两种。第一种语法是使用关键字 function,随后跟上分配给该代码块的函数名:

shell 复制代码
function name {
	commands
}

name 定义了该函数的唯一名称。脚本中的函数名不能重复。

commands 是组成函数的一个或多个 bash shell 命令。调用该函数时,bash shell 会依次执行函数内的命令,就像在普通脚本中一样。

第二种在 bash shell 脚本中创建函数的语法更接近其他编程语言中定义函数的方式:

shell 复制代码
name() {
	commands
}

函数名后的空括号表明正在定义的是一个函数。这种语法的命名规则和第一种语法一样。

使用函数

shell 复制代码
#!/bin/bash
# using a function in a script
function func1 {
	echo "This is an example of a function"
}
count=1
while [ $count -le 5 ]
do
    func1
    count=$[ $count + 1 ]
done
echo "This is the end of the loop"
func1
echo "Now this is the end of the script"

函数定义不一定非要放在 shell 脚本的最开始部分,但是要注意这种情况。如果试图在函数被定义之前调用它,则会收到一条错误消息。

函数返回值

bash shell 把函数视为一个小型脚本,运行结束时会返回一个退出状态码,有 3 种方法能为函数生成退出状态码。

默认的退出状态码

在默认情况下,函数的退出状态码是函数中最后一个命令返回的退出状态码。函数执行结束后,可以使用标准变量$?来确定函数的退出状态码:

shell 复制代码
#!/bin/bash
# testing the exit status of a function
func1() {
	echo "trying to display a non-existent file"
	ls -l badfile
}
func2() {
	ls -l badfile
	echo "trying to display a non-existent file"
}
echo "testing the function: "
func1
echo "The exit status is: $?"
func2
echo "The exit status is: $?"

该函数的退出状态码是函数内部最后一条命令执行返回做的状态,上例中func1返回的状态是1(badfile不存在),func2返回的状态是0(最后一条命令执行成功)

使用return命令

bash shell 会使用 return 命令以特定的退出状态码退出函数。return 命令允许指定一个整数值作为函数的退出状态码,从而提供了一种简单的编程设定方式:

shell 复制代码
#!/bin/bash
# using the return command in a function
function dbl {
    read -p "Enter a value: " value
    echo "doubling the value"
    						# 函数执行一结束就立刻读取返回值。
    return $[ $value * 2 ]  # 退出状态码必须介于 0~255
}
dbl
echo "The new value is $?"

使用函数输出

正如可以将命令的输出保存到 shell 变量中一样,也可以将函数的输出保存到 shell 变量中:

result=$(dbl)

shell 复制代码
#!/bin/bash
# using the echo to return a value
function dbl {
    read -p "Enter a value: " value
    echo $[ $value * 2 ]
}
result=$(dbl) # 注意,result获取的不是dbl执行的状态码
			  # 而是最后一行命令输出的内容echo $[ $value * 2 ]
echo "The new value is $result"

新函数会用 echo 语句来显示计算结果。该脚本会获取 dbl 函数的输出,而不是查看退出状态码。

在函数中使用变量

向函数传递参数

函数可以使用标准的位置变量来表示在命令行中传给函数的任何参数。例如,函数名保存在0 变量中,函数参数依次保存在1、2 等变量中。也可以用特殊变量#来确定传给函数的参数数量。

在脚本中调用函数时,必须将参数和函数名放在同一行,就像下面这样:

func1 $value 10

shell 复制代码
#!/bin/bash
# passing parameters to a function
function addem {
	if [ $# -eq 0 ] || [ $# -gt 2 ]
    then
    	echo -1
    elif [ $# -eq 1 ]
    then
    	echo $[ $1 + $1 ]
    else
    	echo $[ $1 + $2 ]
	fi
}
echo -n "Adding 10 and 15: "
value=$(addem 10 15)
echo $value
echo -n "Let's try adding just one number: "
value=$(addem 10)
echo $value
echo -n "Now try adding no numbers: "
value=$(addem)
echo $value
echo -n "Finally, try adding three numbers: "
value=$(addem 10 15 20)
echo $value

在函数中处理变量

全局变量是在 shell 脚本内任何地方都有效的变量。如果在脚本的主体部分定义了一个全局变量,那么就可以在函数内读取它的值。

在默认情况下,在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问:

shell 复制代码
#!/bin/bash
# using a global variable to pass a value
function dbl {
	value=$[ $value * 2 ]
}

read -p "Enter a value: " value
dbl
echo "The new value is: $value"

$value 变量在函数外定义并被赋值。当 dbl 函数被调用时,该变量及其值在函数中依然有效。如果变量在函数内被赋予了新值,那么在脚本中引用该变量时,新值仍可用。

局部变量:无须在函数中使用全局变量,任何在函数内部使用的变量都可以被声明为局部变量。只需在变量声明之前加上 local 关键字即可:

local temp

也可以在变量赋值语句中使用 local 关键字:

local temp=\[ value + 5 ]

local 关键字保证了变量仅在该函数中有效。如果函数之外有同名变量,那么 shell 会保持这两个变量的值互不干扰。

shell 复制代码
#!/bin/bash
# demonstrating the local keyword
function func1 {
    local temp=$[ $value + 5 ]
    result=$[ $temp * 2 ]
}
temp=4
value=6

func1
echo "The result is $result"
if [ $temp -gt $value ]
then
	echo "temp is larger"
else
	echo "temp is smaller"
fi

数组变量和函数

向脚本函数传递数组变量的方法:先将数组变量拆解成多个数组元素,然后将这些数组元素作为函数参数传递。最后在函数内部,将所有的参数重新组合成一个新的数组变量。

shell 复制代码
#!/bin/bash
# array variable to function test
function testit {
	local sum=0
	local newarray
	newarray=(`echo "$@"`)
	echo "The new array value is: ${newarray[*]}"
	for value in ${newarray[*]}
    do
    	sum=$[ $sum + $value ]
    done
    echo $sum
}

myarray=(1 2 3 4 5)
echo "The original array is ${myarray[*]}"
testit ${myarray[*]}

$myarray变量保存所有的数组元素,然后将其作为参数传递给函数。该函数随后根据参数重建数组变量。

函数向 shell 脚本返回数组变量:函数先用 echo 语句按正确顺序输出数组的各个元素,然后脚本再将数组元素重组成一个新的数组变量:

shell 复制代码
#!/bin/bash
# returning an array value
function arraydblr {
	local origarray
	local newarray
	local elements
	local i
	origarray=($(echo "$@"))
	newarray=($(echo "$@"))
	elements=$[ $# - 1 ]
	for (( i = 0; i <= $elements; i++ ))
	{
		newarray[$i]=$[ ${origarray[$i]} * 2 ]
	}
	echo ${newarray[*]}
}
myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
arg1=$(echo ${myarray[*]})
result=($(arraydblr $arg1))
echo "The new array is: ${result[*]}"

该脚本通过$arg1 变量将数组元素作为参数传给 arraydblr 函数。arraydblr 函数将传入的参数重组成新的数组变量,生成该数组变量的副本。然后对数据元素进行遍历,将每个元素的值翻倍,并将结果存入函数中的数组变量副本。

创建库

bash shell 允许创建函数库文件,然后在多个脚本中引用此库文件。

定义函数库文件 myfuncs.sh

shell 复制代码
# my script functions
function addem {
	echo $[ $1 + $2 ]
}
function multem {
	echo $[ $1 * $2 ]
}
function divem {
    if [ $2 -ne 0 ]
    then
    	echo $[ $1 / $2 ]
    else
    	echo -1
    fi
}

在需要用到这些函数的脚本文件中包含 myfuncs 库文件

使用函数库的关键在于 source 命令。source 命令会在当前 shell 的上下文中执行命令,而不是创建新的 shell 并在其中执行命令。可以用 source 命令在脚本中运行库文件。这样脚本就可以使用库中的函数了。

source 命令有个别名,称作点号操作符,可以用"点"代替

shell 复制代码
#!/bin/bash
# using a library file the wrong way
# 引入函数库
# source ./myfuncs 
# 引入函数库 推荐写法
. ./mufuncs # 注意点后面的空格
result=$(addem 10 15)
echo "The result is $result"
相关推荐
xuanzdhc17 分钟前
Linux 基础IO
linux·运维·服务器
愚润求学23 分钟前
【Linux】网络基础
linux·运维·网络
bantinghy1 小时前
Linux进程单例模式运行
linux·服务器·单例模式
小和尚同志2 小时前
29.4k!使用 1Panel 来管理你的服务器吧
linux·运维
帽儿山的枪手2 小时前
为什么Linux需要3种NAT地址转换?一探究竟
linux·网络协议·安全
shadon1789 天前
回答 如何通过inode client的SSLVPN登录之后,访问需要通过域名才能打开的服务
linux
小米里的大麦9 天前
014 Linux 2.6内核进程调度队列(了解)
linux·运维·驱动开发
程序员的世界你不懂9 天前
Appium+python自动化(三十)yaml配置数据隔离
运维·appium·自动化
算法练习生9 天前
Linux文件元信息完全指南:权限、链接与时间属性
linux·运维·服务器
忘了ʷºᵇₐ9 天前
Linux系统能ping通ip但无法ping通域名的解决方法
linux·服务器·tcp/ip