暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Bash函数实践指南

老柴杂货铺 2025-03-27
92

一、函数定义与基础用法

1. 定义方式

    # 方式1:标准语法(兼容性强)
    myfunc() {
        echo "Hello, $1!"
    }
    # 方式2:使用 `function` 关键字(可读性高)
    function myfunc2 {
        echo "Hello, $1!"
    }

    2. 调用函数

      myfunc "World"  # 输出: Hello, World!
      myfunc2 "Shell" # 输出: Hello, Shell!

      二、参数与返回值

      1. 参数传递

      位置参数:$1, $2, ..., ${10}(第10个及以上参数需加大括号)

      参数列表:$@(所有参数,保留空格分隔),$*(合并为单个字符串)

      参数总数:$#

      示例:统计参数并遍历

        sum_args() {
            local total=0
            for arg in "$@"do
                total=$((total + arg))
            done
            echo "总和: $total"
        }
        sum_args 10 20 30  # 输出: 总和: 60

        2. 返回值处理

        返回状态码:return 0(成功)或 1-255(错误码)

        返回数据:通过 echo 捕获输出

          get_user() {
              local uid=$1
              grep "^$uid:" /etc/passwd | cut -d: -f1
              return $?  # 返回grep命令的退出状态
          }
          username=$(get_user 1000)
          if [[ $? -eq 0 ]]; then
              echo "用户存在: $username"
          fi

          三、变量作用域与局部化

          1. 避免全局污染

            func() {
                local var="局部变量"  # 仅在函数内有效
                global_var="全局变量" # 外部可访问
            }
            func
            echo "$var"       # 无输出(局部变量已销毁)
            echo "$global_var" # 输出: 全局变量

            2. 动态修改变量(引用传递)

              modify_var() {
                  local -n ref=$1  # 通过引用传递变量名
                  ref="新值"
              }
              value="旧值"
              modify_var value
              echo "$value"  # 输出: 新值

              四、高级技巧与调试

              1. 函数嵌套与递归

                # 递归计算阶乘
                factorial() {
                    local n=$1
                    if ((n <= 1)); then
                        echo 1
                    else
                        echo $((n * $(factorial $((n-1)))))
                    fi
                }
                echo "5! = $(factorial 5)"  # 输出: 5! = 120

                2. 错误处理与调试

                严格模式:在脚本开头添加 set -euo pipefail(遇错退出、未定义变量报错、管道失败检测)

                调试输出:

                  debug_func() {
                      set -x          # 开启调试
                      local cmd=$1
                      $cmd
                      set +x          # 关闭调试
                  }
                  debug_func "ls -l"

                  五、实战场景示例

                  1. 批量重命名文件

                    batch_rename() {
                        local ext=$1
                        local prefix=$2
                        local i=1
                        for file in *."$ext"do
                            mv "$file" "${prefix}_${i}.${ext}"
                            ((i++))
                        done
                    }
                    batch_rename "jpg" "photo"  # 重命名所有.jpg文件为photo_1.jpg, photo_2.jpg...

                    2. 系统监控报警

                      check_disk() {
                          local threshold=$1
                          local usage=$(df -h / | awk 'NR==2 {print $5}' | tr -d '%')
                          if ((usage >= threshold)); then
                              echo "警告: 磁盘使用率超过 ${threshold}% (当前: ${usage}%)" >&2
                              return 1
                          fi
                          return 0
                      }
                      check_disk 90 || send_alert_email  # 触发邮件报警

                      3. 自动化备份

                        backup_dir() {
                            local src=$1
                            local dest="/backup/$(basename $src)_$(date +%Y%m%d).tar.gz"
                            tar -czf "$dest" "$src" && echo "备份成功: $dest"
                        }
                        backup_dir "/var/www"  # 生成/backup/www_20231001.tar.gz

                        六、性能优化建议

                        减少子进程调用:避免在循环中频繁调用外部命令(如 awk、sed),改用内置字符串操作。

                        预加载函数:将常用函数定义在单独文件中,通过 source utils.sh 导入。

                        避免递归过深:Bash 默认栈深度有限(可通过 ulimit -s 调整),复杂计算建议改用循环。

                        七、常见问题解决

                        问题解决方案
                        函数参数包含空格或特殊字符
                        传递时用双引号包裹变量:func "$arg"
                        需要返回超过 255 的整数
                        改用 echo
                         输出结果,通过 $(func)
                         捕获
                        函数内部修改外部变量失败
                        使用 declare -n
                         或全局变量(谨慎使用)
                        函数调用后 $?
                         被覆盖
                        立即保存返回值:output=$(func); ret=$?

                        掌握函数技巧,编写高效、易维护的 Bash 脚本,轻松应对自动化运维、数据处理等场景

                        文章转载自老柴杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                        评论