Bash 脚本——用例子解释的函数

在 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; }
紧凑的功能

最佳实践:

  1. 尝试选择任何一种语法并与之保持一致。
  2. 如果您在协作环境中工作,那么每个人在编码时都保持相同的标准非常重要。

命名约定

创建函数时,您必须为函数命名。 函数名称应该是描述性的,并尽量避免其他函数、变量、常量等已经使用的名称。 《蛇案》 是命名函数的首选方式。 在蛇的情况下,单词用下划线分隔。

看看下面 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  
在 Bash 中调用函数

如果您尝试在函数定义之前调用该函数,您将收到以下错误。

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
Exit  状态和返回值Exit 状态和返回值

函数返回的退出状态来自 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
Exit  状态码Exit 状态码

将参数传递给函数

类似于将参数传递给您的 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_functioninside_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
使用 local 关键字的局部变量使用 local 关键字的局部变量

建议阅读:

  • Bash 脚本——用例子解释的变量

使用 local 关键字时,可以在不同的函数中使用相同的变量名。

相同的变量名相同的变量名

小心: 您应该始终尽量避免使用已经用作变量、函数、 bash 关键词。 以上 example 显示只是为了理解行为。

模块化和可重用性

理解和编写函数可以快速完成。 但是编写好的函数需要时间来更好地理解环境。 正如在介绍部分已经指出的那样,与 bash 功能可以实现大量的模块化和可重用性。

让我们来一个 example. 您已经创建了 20 个脚本,并且在每个脚本中,您都包含了 log_cleanup 我们在前面的章节中看到了执行内务管理任务的函数。 您可以创建一个函数定义并将其导入到 20 个脚本中,而不是将此函数包含在所有 20 个脚本中。 通过这种方式,您可以实现模块化以及可重用的功能。 这类似于 进口 python中的语句, 包括 C中的语句等

看看下面的图片。 我创建了两个名为 script1.shscript2.shlog_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 重定向