Day 6:Shell函数精要——让你的代码拥有“超能力“的魔法书

目录

    • 一、函数基础:定义你的第一个"超能力"
      • 1. 两种定义方式(选你顺眼的)
      • 2. 调用与传参(注意参数作用域)
    • 二、返回值黑科技:超越return的限制
      • 1. 传统状态码(0-255限制)
      • 2. 现代方案:echo输出结果
      • 3. 返回数组(高级技巧)
    • 三、函数库:打造你的"复仇者联盟"
      • 1. 创建公共库(lib.sh)
      • 2. 调用库函数
    • 四、高阶技巧:让函数更强大
      • 1. 动态参数传递("魔法变量")
      • 2. 函数嵌套与递归
      • 3. 函数钩子(Hook)技术
    • 五、避坑指南:函数开发的"七宗罪"
      • 1.忘记local声明:污染全局变量
      • 2.过度使用子进程:性能杀手
      • 3.忽略返回值检查:
    • 六、实战:智能部署框架
    • 课后挑战:自动化测试框架

开篇:从"重复造轮子"到"模块化大师"

想象你在玩乐高:

  • 新手做法:每次需要轮子都重新捏黏土
  • 高阶玩法:提前造好标准轮子,随时调用

Shell函数就是你的代码乐高积木,今天教你打造可复用的"超能力模块"!

一、函数基础:定义你的第一个"超能力"

1. 两种定义方式(选你顺眼的)

# 方式1:正统派(推荐)
function greet() {
    local name="$1"
    echo "Hello, $name! 今天是$(date +%F)"
}

# 方式2:极简派
log_error() {
    echo "[ERROR $(date +%T)] $@" >&2
}

行业惯例:

  • 公共函数用function声明更醒目
  • 内部函数用简写节省空间

2. 调用与传参(注意参数作用域)

greet "Shell学徒"  # 输出:Hello, Shell学徒! 今天是2023-08-01
log_error "磁盘空间不足"  # 输出到标准错误流

二、返回值黑科技:超越return的限制

1. 传统状态码(0-255限制)

is_root() {
    [ $(id -u) -eq 0 ]
    return $?  # 可省略
}
is_root && echo "管理员模式" || echo "请使用sudo"

2. 现代方案:echo输出结果

get_ip() {
    local iface=$1
    ip addr show $iface | grep -oP 'inet \K[\d.]+'
}
server_ip=$(get_ip eth0)

3. 返回数组(高级技巧)

get_users() {
    local users=($(cut -d: -f1 /etc/passwd))
    echo "${users[@]}"
}
user_array=($(get_users))  # 注意外层括号

三、函数库:打造你的"复仇者联盟"

1. 创建公共库(lib.sh)

#!/bin/bash
# 日志工具
log::info() {
  echo -e "\033[32m[INFO]\033[0m $(date '+%F %T') $@"
}

# 数学工具
math::add() {
  echo $(($1 + $2))
}

# 安全工具
security::check_port() {
  netstat -tuln | grep -q ":$1 "
}

2. 调用库函数

source ./lib.sh

log::info "系统初始化开始"
security::check_port 80 && log::info "80端口已被占用"
result=$(math::add 10 20)

四、高阶技巧:让函数更强大

1. 动态参数传递(“魔法变量”)

call_api() {
    local method=$1
    local url=$2
    shift 2  # 移除非body参数
    curl -X $method "$url" -d "$@"
}

call_api POST http://api.com name=John age=30

2. 函数嵌套与递归

# 递归计算阶乘
factorial() {
    local n=$1
    [ $n -le 1 ] && echo 1 && return
    echo $(( n * $(factorial $((n-1))) ))
}
factorial 5  # 输出120

3. 函数钩子(Hook)技术

before_install() {
    echo "安装前检查..."
    [ -f "/tmp/lock" ] && return 1
}

after_install() {
    echo "清理临时文件..."
    rm -f /tmp/*
}

main() {
    before_install || exit 1
    # 安装逻辑...
    after_install
}

五、避坑指南:函数开发的"七宗罪"

1.忘记local声明:污染全局变量

bad_func() {
  count=10  # 全局变量!
}

2.过度使用子进程:性能杀手

slow_func() {
  result=$(echo "scale=2; $1/$2" | bc)  # 每次调用都启动bc
}

3.忽略返回值检查:

danger() {
  rm -rf "/tmp/$1"  # 如果$1为空...
}

六、实战:智能部署框架

#!/bin/bash
source ./lib.sh

deploy() {
    local env=$1
    local version=$2
    
    log::info "开始部署[$env]环境v$version"
    
    security::check_port 8080 && {
        log::error "8080端口被占用"
        return 1
    }
    
    # 模拟部署过程
    for i in {1..5}; do
        sleep 0.5
        echo -n "." >&2
    done
    
    log::info "部署成功完成"
}

main() {
    case "$1" in
        prod) deploy prod "$2" ;;
        test) deploy test "$2" ;;
        *) echo "用法: $0 {prod|test} 版本号" ;;
    esac
}

main "$@"

课后挑战:自动化测试框架

需求:

  • ✅ 封装测试函数(assert_equal, assert_file_exists等)
  • ✅ 支持从YAML文件读取测试用例
  • ✅ 生成带颜色的测试报告

示例输出:

$ ./tester.sh login_test.yaml
[PASS] 测试登录功能-正常流 (0.2s)
[FAIL] 测试登录功能-错误密码 (预期401实际200)

你可能感兴趣的:(Shell编程,linux)