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

在 Bash shell 脚本中,函数是将指令集组合在一起以获得特定结果的方法。 您可以将函数视为一个迷你脚本。 在某些编程语言中,函数也称为过程和方法。 函数是实现模块化和可重用性的好方法。

在这篇文章中,我将解释如何使用函数 bash Linux 中的脚本和示例。 你会很舒服地使用 bash 在本文结束时的功能。

内容

  1. 如何在 Bash 中定义函数
  2. 命名约定
  3. 如何在 Bash 中调用函数
  4. Exit 状态 & 返回值
  5. 将参数传递给函数
  6. 函数的变量范围
  7. 模块化和可再利用性
  8. 结论

如何在 Bash 中定义函数

在使用函数时,您必须了解两件重要的事情。

  • 定义函数,
  • 调用函数。

类似于您的创建方式 bash 脚本并运行它们,您应该定义函数并调用它来运行函数。

有两种语法方式来定义函数 bash. 第一种方法是使用 bash 内置关键字 "function" 后跟函数的名称。 代码块会写在里面 大括号 {}.

function [name] {
Block of code
}

第二种方式是创建一个没有关键字的函数 "function". 以函数名称开头,后跟括号。

[name](){
Block of Code
}

选择哪一个? 好吧,这始终是个人选择。 选择其中之一没有任何缺点。

您还可以编写单行函数,这些函数被称为 紧凑的功能. 在紧凑函数中,大括号内的每一行代码都用 分号 (;).

启动您的终端并编写一段多行函数。 现在按向上箭头键,您将看到您在多行中编写的任何内容都将转换为紧凑函数。

[name](){ first_line; second_line; }
紧凑的功能

最佳实践:

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

命名约定

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

看看下面的例子。 我创建了一个名为的函数 "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
将参数传递给函数将参数传递给函数

正如您在上面的屏幕截图中看到的,我将目录名称和天数作为参数传递。

函数的变量范围

在函数内部或函数外部创建变量时,可以全局访问它。 默认情况下,变量是在全局范围内创建的。

看看下面的例子。 如果您尝试访问两个变量 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 关键词。 上面的例子只是为了理解行为。

模块化和可再利用性

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

让我们举个例子。 您已经创建了 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 重定向

BASHBash 函数Bash 脚本Bash 提示CLICommandlineLinuxScriptingShell 脚本