主题
  • 默认模式
  • 浅蓝色模式
  • 淡绿色模式
  • 深夜模式

Shell 函数

在 Linux Shell 环境中,用户可通过定义函数来实现函数式编程。这些自定义函数能在 Shell 脚本中被多次调用,这有助于脚本的模块化设计,并显著提高代码的可维护性和可复用性。

Shell 函数是一种将一系列命令封装起来,以便重复使用的有效方式,它们类似于其他编程语言中的函数。


函数的基本语法

1. 使用function关键字进行函数声明,语法更显式,兼容性更高:

php
复制
function function_name {
    command1
    ...
}

2. 省略function关键字,使函数定义更简洁,并符合 POSIX 标准风格:

php
复制
function_name() {
    command1
    ...
}

函数的基本调用

调用函数非常简单,只需要在脚本中写下它的名字即可,就像执行一个普通命令一样。

bash
复制
#!/bin/bash
# author: 开创者教程
# url: www.kaicz.com

# 定义函数
demoFun(){
    echo "这是我的第一个 shell 函数!"
}

echo "-----函数开始执行-----"
demoFun # 调用函数
echo "-----函数执行完毕-----"

✅ 输出结果:

-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----

函数的返回值

在 Shell 函数中,数据的返回主要通过以下两种机制实现:

1. 退出状态码 (Exit Status)

函数执行结束后都会返回一个退出状态码:0 表示成功,非 0 值表示失败或特定错误。使用return语句可以显式指定这个状态码。

  • return 0:表示函数执行成功。
  • return 1:(或其他非零值): 表示函数执行失败或出现某种错误。

✅ 下面是一个检查文件是否存在的实例:

bash
复制
#!/bin/bash
# author: 开创者教程
# url: www.kaicz.com

file_exists() {
    if [ -f "$1" ]; then
        return 0 # 成功,文件存在
    else
        return 1 # 失败,文件不存在
    fi
}

# 调用函数并检查其返回值
if file_exists "/etc/hosts"; then
    echo "该文件存在!"
else
    echo "该文件不存在!"
fi

2. 输出结果 (Output)

更常见方式是让函数像命令一样,通过标准输出 (stdout) “返回” 数据。调用者可以使用命令替换$(...)来捕获这个输出。

✅ 下面是一个获取系统信息的实例:

bash
复制
#!/bin/bash
# author: 开创者教程
# url: www.kaicz.com

get_system_info() {
    local user=$(whoami)
    local kernel=$(uname -r)
    echo "当前用户: $user, 内核版本: $kernel"
}

# 捕获函数的输出并存入变量
info=$(get_system_info)
echo "系统信息: $info"

✅ 输出结果:

系统信息: 当前用户: username, 内核版本: 5.15.0-91-generic

请注意:在函数中应使用echo(而不是return)来返回需要被脚本使用的字符串或数据。


向函数传递参数

Shell 函数具备接收参数的能力,这些参数在函数内部通过特定的位置变量进行访问,其使用方式与脚本接收命令行参数完全一致。

  • $1: 获取第一个参数
  • $2: 获取第二个参数
  • $#: 统计传递的参数总数
  • $@: 获取所有参数的列表

✅ 下面是一个计算两个数和的实例:

bash
复制
#!/bin/bash
# author: 开创者教程
# url: www.kaicz.com

add() {
    local sum=$(( $1 + $2 ))  # 计算前两个参数的和
    echo $sum                 # 输出计算结果
}

result=$(add 5 10)            # 调用函数并传递参数
echo "两数之和为: $result"

✅ 输出结果:

两数之和为: 15

变量的作用域 (Scope)

默认情况下,在函数内部定义的变量是 全局的!这意味着在函数内部修改一个变量会影响到脚本的其他部分。

✅ 下面是一个危险的全局变量实例:

bash
复制
#!/bin/bash
# author: 开创者教程
# url: www.kaicz.com

# 全局变量
global_var="初始全局变量值"

# 修改变量的函数
change_var() {
    global_var="函数内部修改的值"  # 这里修改了全局变量
    local local_var="这是局部变量,外部无法访问"
}

echo "执行函数前: $global_var"
change_var
echo "执行函数后: $global_var"
echo "尝试访问局部变量: ${local_var:-变量不存在}"

✅ 输出结果:

执行函数前: 初始全局变量值
执行函数后: 函数内部修改的值
尝试访问局部变量: 变量不存在

为了避免这种副作用,应始终使用local关键字在函数内部声明变量,将其限制为局部变量。

bash
复制
#!/bin/bash

safe_function() {
    local safe_var="使用 local 确保安全"
    # 这样不会影响外部变量
}

一个实用的函数

下面是一个结合了以上所有概念的实用函数,用于备份一个文件,并在备份前检查是否存在。

bash
复制
#!/bin/bash

# 定义备份函数
backup_file() {
    local src_file="$1"
    local backup_dir="./backups"

    # 检查源文件是否存在
    if [ ! -f "$src_file" ]; then
        echo "Error: Source file '$src_file' does not exist."
        return 1
    fi

    # 创建备份目录(如果不存在)
    mkdir -p "$backup_dir"

    # 生成带时间戳的备份文件名
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local backup_file="$backup_dir/$(basename "$src_file")_$timestamp.bak"

    # 执行拷贝
    cp "$src_file" "$backup_file"

    # 检查拷贝是否成功
    if [ $? -eq 0 ]; then
        echo "Backup successful: '$backup_file'"
        return 0
    else
        echo "Backup failed for '$src_file'."
        return 2
    fi
}

# 调用函数
backup_file "important_document.txt"


评论区 0
发表评论