Bash 初学者系列 #1:在 Bash 中使用函数
当您的 bash 脚本变得越来越大时,事情会变得非常混乱!
您可能会发现自己在 bash 脚本的不同部分一次又一次地重写相同的代码片段。
幸运的是,您可以通过在 bash 中使用函数来避免重写代码,这将使您的脚本更有组织性和可读性。
在本教程中,您将学习在 bash shell 脚本中创建函数、返回函数值和传递函数参数。
此外,您将了解变量作用域如何工作以及如何定义递归函数。
在 bash 中创建函数
声明 bash 函数有两种不同的语法。以下语法是创建 bash 函数最常用的方法:
function_name () {
commands
}
第二种不太常用的创建 bash 函数的方法是从保留的工作函数开始,后跟函数名称,如下所示:
function function_name {
commands
}
在使用函数时,您应该清楚以下几点:
- 除非您调用函数,否则函数永远不会运行/执行。
- 函数定义必须先于对该函数的任何调用。
任何时候你想要一个函数运行,你只需要调用它!函数调用是通过简单地引用函数名来完成的。
看看下面的linuxmi.sh bash 脚本:
#!/bin/bash
hello () {
echo "Hello World! Linux迷 www.linuxmi.com"
}
hello
hello
hello
我定义了一个名为 hello 的函数,它只是将“Hello World”行回显到终端。请注意,我执行了三个 hello 函数调用,因此如果您运行该脚本,您将看到屏幕上打印了三次“Hello World”行:
在 bash 中返回函数值
在许多编程语言中,函数在调用时确实会返回一个值;但是,bash 不是这种情况,因为 bash 函数不返回值。
当 bash 函数完成执行时,它返回在 $? 多变的。零表示执行成功或非零正整数 (1-255) 表示失败。
您可以使用 return 语句来更改函数的退出状态。例如,查看以下 linuxmi.sh 脚本:
#! /bin/bash
//Linux迷 www.linuxmi.com
error () {
blabla
return 0
}
error
echo "错误函数的返回状态为: $?"
如果运行 linuxmi.sh bash 脚本,您可能会对输出感到惊讶:
如果没有return 0语句,error
函数将永远不会返回非零退出状态,因为 blabla 会导致 未找到命令 错误。
正如您所看到的,即使 bash 函数不返回值,我还是通过改变函数退出状态来解决这个问题。
您还应该知道 return 语句会立即终止函数。
将参数传递给 bash 函数
您可以将参数传递给函数,就像您可以将参数传递给 bash 脚本一样。您只需在执行函数调用时包含参数。
为了演示,让我们看一下以下www.linuxmi.com.sh bash 脚本:
#!/bin/bash
#Linux迷 www.linuxmi.com
iseven () {
if [ $(($1 % 2)) -eq 0 ]; then
echo "$1 是偶数。"
else
echo "$1 是奇数。"
fi
}
iseven 5
iseven 2
iseven 28
iseven 199
iseven() 函数测试数字是偶数还是奇数。我对 iseven() 进行了四次函数调用。对于每个函数调用,我提供了一个数字,它是对 iseven() 函数的第一个扩充,并由函数定义中的 $1 变量引用。
让我们运行 www.linuxmi.com.sh bash 脚本以确保其正常工作:
您还应该清楚 bash 函数参数和bash 脚本参数是两个不同的东西。为了对比差异,请查看以下 linuxmi.sh bash 脚本:
#!/bin/bash
#Linux迷 www.linuxmi.com
fun () {
echo "$1 是 fun() 第一个参数。"
echo "$2 是 fun() 第二个参数。"
}
echo "$1 是脚本的第一个参数。"
echo "$2 是脚本的第二个参数。"
fun linuxmi 93139
使用几个参数运行脚本并观察结果:
如您所见,即使您使用相同的变量 $1 和 $2 来引用脚本参数和函数参数,当从函数内调用时它们会产生不同的结果。
bash 函数中的局部变量和全局变量
Bash 变量可以具有全局或局部作用域。无论范围如何,您都可以在 bash 脚本中的任何位置访问全局变量。相反,局部变量只能从它们的函数定义中访问。
为了演示,请查看以下linuxmi.com.sh bash 脚本:
#!/bin/bash
#Linux迷 www.linuxmi.com
a1='X'
a2='Y'
myfun() {
local v1='Z'
v2='W'
echo "Inside myfun(): a1: $a1, a2: $a2"
}
echo "Before calling myfun(): v1: $a1, a2: $a2"
myfun
echo "After calling myfun(): a1: $a1, a2: $a2"
我首先定义了两个全局变量a1和a2。然后在myfun()定义中,我使用local关键字定义了一个局部变量a1并修改了全局变量a2。请注意,您可以为不同函数中的局部变量使用相同的变量名。
现在让我们运行脚本:
从脚本输出中,您可以得出以下结论:
- 与全局变量同名的局部变量将优先于函数体内的全局变量。
- 您可以从函数内更改全局变量。
递归函数
递归函数是一个调用自身的函数!当您尝试解决可以分解为更小的子问题的编程问题时,递归函数会派上用场。
阶乘函数是递归函数的一个典型例子。查看以下 linuxmi.com.sh bash 脚本:
#!/bin/bash
#Linux迷 www.linuxmi.com
factorial () {
if [ $1 -le 1 ]; then
echo 1
else
last=$(factorial $(( $1 -1)))
echo $(( $1 * last ))
fi
}
echo -n "4! is: "
factorial 4
echo -n "5! is: "
factorial 5
echo -n "6! is: "
factorial 6
任何递归函数都必须以一个基本情况开始,该基本情况必然会结束递归函数调用链。在factorial()函数中,基本情况定义如下:
if [ $1 -le 1 ]; then
echo 1
现在推导阶乘函数的递归情况。要计算数字n的阶乘,其中n是大于 1 的正数,您可以将n乘以n-1的阶乘:
factorial(n) = n * factorial(n-1)
让我们使用上面的等式来编写这个递归案例:
last=$(factorial $(( $1 -1)))
echo $(( $1 * last ))
现在运行脚本并确保获得正确的结果:
作为附加练习,尝试编写一个递归函数来计算第 n 个斐波那契数。首先,尝试提出基本情况,然后提出递归情况;你明白了!
The post Bash 初学者系列 #1:在 Bash 中使用函数 first appeared on Linux迷.
共有 0 条评论