网站搜索

理解和编写 Shell 脚本中的函数 - 第 VI 部分


函数在任何编程语言中都发挥着重要作用。与许多真实的编程语言一样,bash 的函数的实现有限。

什么是函数?

在编程中,函数是执行特定任务的程序的命名部分。从这个意义上说,函数是一种过程或例程。当调用函数时,程序离开当前代码段并开始执行函数内的第一行。每当存在重复代码或任务重复时,请考虑使用函数。

例如,考虑这样的情况:我们需要在特定程序的多个阶段查找数字的阶乘。我们不必每次都编写整个代码(用于计算阶乘),而是可以在块内编写一次计算阶乘的代码部分,并在多个场合重复使用相同的代码。

我们为什么要写函数?

  1. 它可以帮助我们重用代码。
  2. 提高程序的可读性。
  3. 有效使用程序内的变量。
  4. 允许我们逐部分测试程序。
  5. 将程序显示为一堆子步骤。
shell脚本中的函数

shell脚本中编写函数的一般语法包括以下几种方式。

function func_name {
	. . .
	commands
	. . .
}

or

func_name ( ) {
	. . .
	commands
	. . .
}

Opening curly braces can also be used in the second line as well.

func_name ( )
{
	. . .
	commands
	. . .
}

您始终可以像我们通常在 shell 脚本中一样在这些功能块中编写有效的命令。现在让我们尝试编写一个简单的脚本,其中包含一个小函数。

#!/bin/bash

call_echo ( ) {
	echo ‘This is inside function’
}

op=$1

if [ $# -ne 1 ]; then
	echo "Usage: $0 <1/0>"
else
	if [ $1 = 0 ] ; then
		echo ‘This is outside function’
	elif [ $1 = 1 ] ; then
		call_echo
	else
		echo ‘Invalid argument’
	fi
fi

exit 0

函数定义必须在第一次调用之前。没有什么比在调用函数之前“声明函数”更好的了。我们总是可以将函数嵌套在函数中。

注意:- 编写空函数总是会导致语法错误。

当同一函数被多次定义时,最终版本就是被调用的版本。让我们举个例子。

#!/bin/bash

func_same ( ) {
	echo ‘First definition’
}

func_same ( ) {
	echo ‘Second definition’
}

func_same

exit 0
函数接受参数并返回值

让我们更深入地考虑采用参数和返回值的函数。为了从函数返回一个值,我们使用内置的“return”shell。语法如下。

func_name ( ) {
	. . .
	commands
	. . .
	return $ret_val
}

类似地,我们可以将参数传递给用空格分隔的函数,如下所示。

func_name $arg_1 $arg_2 $arg_3

在函数内部,我们可以按 $1、$2、$3 等顺序访问参数。查看以下示例脚本,使用函数查找两个整数的最大值,以增加清晰度。

#!/bin/bash

USG_ERR=7

max_two ( ) {
	if [ "$1" -eq "$2" ] ; then
		echo 'Equal'
		exit 0
	elif [ "$1" -gt "$2" ] ; then
		echo $1
	else
		echo $2
	fi
}

err_str ( ) {
	echo "Usage: $0 <number1>  <number2>"
	exit $USG_ERR
}

NUM_1=$1
NUM_2=$2
x
if [ $# -ne 2 ] ; then
	err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
	if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then  
		max_two $NUM_1 $NUM_2
	else
		err_str
	fi
else
	err_str
fi

exit 0

上面的代码看起来有点复杂,但是我们仔细看一下就很简单了。首先嵌套 if-else if 行用于验证目的,即借助正则表达式检查参数的数量和类型。之后,我们使用两个命令行参数调用该函数并在其中显示结果本身。这是因为我们无法从函数返回大整数。解决此问题的另一种方法是使用全局变量将结果存储在函数内。下面的脚本解释了这种方法。

#!/bin/bash

USG_ERR=7
ret_val=

max_two ( ) {
	if [ "$1" -eq "$2" ] ; then
		echo 'Equal'
		exit 0
	elif [ "$1" -gt "$2" ] ; then
		ret_val=$1
	else
		ret_val=$2
	fi
}

err_str ( ) {
	echo "Usage: $0 <number1>  <number2>"
	exit $USG_ERR
}

NUM_1=$1
NUM_2=$2

if [ $# -ne 2 ] ; then
	err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
	if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then  
		max_two $NUM_1 $NUM_2
		echo $ret_val
	else
		err_str
	fi
else
	err_str
fi

exit 0

现在尝试一些令人兴奋的问题,这些问题在之前的 shell 脚本系列中使用函数进行了解释,如下所示。

  1. 了解基本的 Linux Shell 脚本语言技巧 – 第一部分
  2. 供 Linux 新手学习 Shell 编程的 5 个 Shell 脚本 - 第二部分
  3. 畅游 Linux BASH 脚本世界 – 第三部分
  4. Linux Shell 编程的数学方面 – 第四部分
  5. 使用 Shell 脚本语言计算数学表达式 - 第五部分

在下一部分中,我将更深入地了解功能特性,例如使用局部变量、递归等。随时关注评论。