在 Bash shell 脚本中,函数是将一组指令组合在一起以获得特定结果的方法。 您可以将函数视为迷你脚本。 在某些编程语言中,函数也称为过程和方法。 函数是实现模块化和可重用性的好方法。
在这篇文章中,我将解释如何使用函数 bash Linux 中的脚本和示例。 你会很舒服地使用 bash 本文末尾的功能。
如何在 Bash 中定义函数
在使用函数时,您必须了解两件重要的事情。
- 定义函数,
- 调用函数。
类似于您的创建方式 bash 脚本并运行它们,您应该定义函数并调用它以使函数运行。
定义函数有两种语法方式 bash. 第一种方法是使用 bash 内置关键字 "function"
后跟函数的名称。 代码块将写在里面 大括号 {}
.
function [name] {
Block of code
}
第二种方法是创建一个没有关键字的函数 "function"
. 以函数名开头,后跟括号。
[name](){
Block of Code
}
选择哪一个? 好吧,这始终是个人选择。 选择其中之一没有缺点。
您还可以编写称为的单行函数 紧凑函数. 在紧凑函数中,大括号内的每一行代码都用 分号 (;
).
启动您的终端并编写一个多行函数。 现在按向上箭头键,您将看到您在多行中编写的任何内容都将转换为紧凑函数。
[name](){ first_line; second_line; }
最佳实践:
- 尝试选择任何一种语法并与之保持一致。
- 如果您在协作环境中工作,那么每个人在编码时都保持相同的标准非常重要。
命名约定
创建函数时,您必须为函数命名。 函数名称应该是描述性的,并尽量避免其他函数、变量、常量等已经使用的名称。 《蛇案》 是命名函数的首选方式。 在蛇的情况下,单词用下划线分隔。
看看下面 example. 我创建了一个名为 "hello_world"
在蛇案例风格中,它只会将 hello world 打印到标准输出(终端)。
hello_world() {
echo "Running Simple Hello World Function"
}
hello_world
如何在 Bash 中调用函数
让我们创建一个简单的清理函数,名为 "log_cleanup"
. 此功能的目的是删除 ".log"
超过 30 天的文件。
log_cleanup(){ echo "Running Cleanup On Older Logs - 30 days" find /home/karthick/Documents/Projects/logs/ -name "*.log" -type f -mtime +30 -delete echo "Cleanup Completed" }
该函数已定义,但这足以让该函数完成其工作吗? 绝对不。 您必须调用该函数才能执行该函数。
要调用该函数,只需在函数定义后键入函数名称:
#!/usr/bin/env bash #### FUNCTION DEFINITION #### log_cleanup(){ echo "Running Cleanup On Older Logs - 30 days" find /home/karthick/Documents/Projects/logs -name "*.log" -type f -mtime +30 -delete echo "Cleanup Completed" } # Calling the function log_cleanup
如果您尝试在函数定义之前调用该函数,您将收到以下错误。
line 3: log_cleanup: command not found

为什么这样? 运行脚本时,代码将从上到下逐行解释。 它将读取函数并将其加载到 bash 环境(记忆)。 但是在这里,您在解释器甚至读取函数并将其加载到其环境之前调用该函数。
当你从另一个函数内部调用一个函数时,你的函数定义可以是除第一个函数之外的任何顺序。 看看下面的图片。 功能 功能2 被称为 功能1 和 功能3 被称为 功能2 在他们的定义之前。 但 功能1 先定义然后调用。 到……的时候 功能1 被调用的所有函数定义都已经被解释并加载到环境中。

Exit 状态和返回值
每个 Linux 命令都返回一个退出状态 (0-255)。 零被称为成功,其余的退出代码被称为具有不同含义的失败。 同样,当你运行一个函数时,它也会返回函数中最后一个运行命令的退出状态。
让我再次运行相同的“清理”功能。 但是我给出了一条在我的机器上不可用的路径,所以 find
命令将失败。 我在用 $?
如镜像所显示,得到脚本内的退出状态。
Running Cleanup On Older Logs - 30 days find: '/home/karthick/Documents/Projectss/logs': No such file or directory Cleanup Completed Exit status of function log_cleanup is ⇒ 0

函数返回的退出状态来自 echo
作为函数内的最后一个命令运行的命令。 这不是您可能期望的行为。
要克服这种行为,您可以使用 bash 内置 "return"
陈述。
$ type -a return
return is a shell builtin
返回接受一个整数 [N] value 并且它退出函数并将返回值提供给它的调用者(函数)。 在使用 return 语句之前,你必须了解如何使用 return 语句的一些规则。 如前所述,return 接受 0-255 之间的整数值。 如果未传递参数(整数值)或值超过 255,则返回语句将使用最后运行命令的退出状态。
让我用回报来修复 "cleanup"
功能行为。 在这里,我使用条件语句和 return 命令。
#!/usr/bin/env bash #### FUNCTION DEFINITION #### log_cleanup(){ echo "[ INFO ] - Running Cleanup On Older Logs - 30 days" if [[ -d "/home/karthick/Documents/Projectss/logs" ]] then find -name "*.log" -type f -mtime +30 -delete echo "[ SUCCESS] - Cleanup Completed" else echo "[ ERROR ] - Directory path wrong... Cleanup has not happened..." return 1 fi } # Calling the function log_cleanup echo "++ Exit status of log_cleanup function is ==> $?"
看看下面的输出。 函数正在返回 退出代码 1 从返回语句。
[ INFO ] - Running Cleanup On Older Logs - 30 days
[ ERROR ] - Directory path wrong… Cleanup has not happened…
++ Exit status of log_cleanup function is ==> 1

将参数传递给函数
类似于将参数传递给您的 bash 脚本,函数也接受参数。 令人困惑的部分是,函数使用相同的 $1
…$9
访问参数的特殊变量与将参数传递给脚本相同。 您必须了解在函数内部和外部使用此特殊变量时会发生什么。
cat > arg_test.sh #!/bin/bash echo "Value passed in $1 is = $1" howdy(){ echo "value of $1 inside function is = $1" } howdy # Function Call
复制并运行上面的代码片段以查看差异。 字符串 "Howdy"
作为第一个参数传递给脚本。
$ ./arg_test.sh howdy
Value passed in $1 is = howdy
value of $1 inside function is =
从输出中可以看到 $1
函数内部正在打印一个空值,因为 $1
函数内部不同于 $1
尽管它们共享相同的名称,但在函数之外。
要将参数传递给函数,请在函数名称后留一个空格并传递您的参数,如下图所示。 每个由空格分隔的参数将被分配其各自的变量 $1
…$N
你可以在函数内部使用这个变量来处理参数。
log_cleanup $1 $2 ….. $N

正如您在上面的屏幕截图中看到的,我将目录名称和天数作为参数传递。
函数的变量范围
当您在函数内部或函数外部创建变量时,可以全局访问它。 默认情况下,变量是在全局范围内创建的。
看看下面 example. 如果您尝试访问这两个变量 outside_function
和 inside_function
,它们的值是可访问的。 这意味着即使函数运行并退出,在函数内部创建的变量也可以全局访问。
#!/bin/bash outside_function="This variable is from outside the function" func1(){ inside_function="This variable is from inside the func1" } func1 echo $outside_function echo $inside_function

在某些编程语言中,这可能不是这种行为,并且在函数内部创建的变量将在函数运行时可用。 但在 bash,行为不同。
要使变量成为函数的局部变量,您可以使用 bash 内置 "local"
关键词。 local 关键字将变量范围从全局限制为局部,并且该变量只能在函数运行时访问。
#!/bin/bash
outside_function="This variable is from outside the function"
func1(){
local inside_function="This variable is from inside the func1"
}
func1
echo $outside_function
echo $inside_function

建议阅读:
- Bash 脚本——用例子解释的变量
使用 local 关键字时,可以在不同的函数中使用相同的变量名。

小心: 您应该始终尽量避免使用已经用作变量、函数、 bash 关键词。 以上 example 显示只是为了理解行为。
模块化和可重用性
理解和编写函数可以快速完成。 但是编写好的函数需要时间来更好地理解环境。 正如在介绍部分已经指出的那样,与 bash 功能可以实现大量的模块化和可重用性。
让我们来一个 example. 您已经创建了 20 个脚本,并且在每个脚本中,您都包含了 log_cleanup
我们在前面的章节中看到了执行内务管理任务的函数。 您可以创建一个函数定义并将其导入到 20 个脚本中,而不是将此函数包含在所有 20 个脚本中。 通过这种方式,您可以实现模块化以及可重用的功能。 这类似于 进口 python中的语句, 包括 C中的语句等
看看下面的图片。 我创建了两个名为 script1.sh
和 script2.sh
和 log_cleanup
函数被写入一个名为 cleanup.sh
.

我正在通过运行 source
命令。 这 source
命令将运行作为其参数传递的文件并将变量或函数加载到当前 bash 会议。 当你跑步时这样 log_cleanup
从另一个脚本文件中,该函数已经加载到当前环境并且可以访问。

从上图中,您可以了解这些论点是如何有帮助的。 只有一个函数定义,根据用例,我可以修改函数以接受不同的参数和不同的脚本。
小心: 你也可以运行你的shell脚本 source
命令将在当前 shell 中运行脚本,而不是创建一个子 shell 来运行脚本。
结论
在本指南中,我们通过示例讨论了 Bash 函数以及如何在脚本中定义和调用函数。 要熟悉函数,您必须使用不同的用例来练习函数。 如果您有任何问题或反馈,请随时通过下面的评论部分告诉我们。
相关阅读:
- Bash 脚本——用例子解释 For 循环
- Bash 脚本 – While 和 until 循环用示例解释
- 定义带和不带导出的 Bash 变量之间的区别
- 用 Linux 中的示例解释 Bash Echo 命令
- Bash Heredoc 初学者教程
- 用示例解释 Bash 重定向