【shell】函数用法的详解

一、函数基础

函数是 Shell 脚本中用于代码复用模块化设计的核心工具,可将重复逻辑封装为独立单元。

1. 定义与调用
# 定义方式1:function 关键字
function say_hello() {
    echo "Hello, $1!"
}

# 定义方式2:简化语法
show_time() {
    date +"%Y-%m-%d %H:%M:%S"
}

# 调用函数
say_hello "World"    # 输出:Hello, World!
current_time=$(show_time)
echo "当前时间: $current_time"
2. 参数传递
  • 位置参数:函数内通过 $1$2 获取参数
  • 特殊变量$#(参数个数)、$@(所有参数数组)
sum() {
    local total=0
    for num in "$@"; do
        ((total += num))
    done
    echo $total
}

result=$(sum 10 20 30)   # 输出:60

二、作用域与变量
1. 局部变量
  • local 关键字:限制变量作用域仅在函数内
test_scope() {
    local var1="内部变量"
    var2="全局变量"
}
test_scope
echo $var1   # 空值(局部变量不可见)
echo $var2   # 输出:全局变量
2. 返回值机制
  • 默认返回值:函数最后一条命令的退出状态码($?
  • 显式返回return N(0-255)
check_file() {
    [[ -f "$1" ]] && return 0 || return 1
}
check_file "/etc/hosts"
if [ $? -eq 0 ]; then
    echo "文件存在"
fi

三、高级用法
1. 返回复杂数据
# 返回字符串
get_config() {
    echo "host=127.0.0.1"
    echo "port=3306"
}

# 读取多行返回值到数组
mapfile -t config < <(get_config)
echo "Host: ${config[0]#*=}"   # 输出:127.0.0.1
2. 递归调用
factorial() {
    local n=$1
    if ((n <= 1)); then
        echo 1
    else
        echo $((n * $(factorial $((n-1)))))
    fi
}
echo "5! = $(factorial 5)"   # 输出:120
3. 函数库封装
# 文件:utils.sh
#!/bin/bash
log() {
    echo "[$(date)] $1" >> "/var/log/myscript.log"
}

# 主脚本中引用
source utils.sh
log "程序启动"

四、实战场景示例
1. 日志处理模块
# 定义日志级别函数
log_info() { log "INFO" "$1"; }
log_error() { log "ERROR" "$1"; }

log() {
    local level="$1"
    local message="$2"
    printf "[%s] %-5s - %s\n" "$(date +'%Y-%m-%d %T')" "$level" "$message"
}

log_info "用户登录成功"
log_error "数据库连接失败"
2. 批量文件处理
process_images() {
    local output_dir="$1"
    mkdir -p "$output_dir"
    for img in *.jpg; do
        convert "$img" -resize 800x600 "$output_dir/$img"
    done
}

# 调用
process_images "./thumbnails"
3. 服务状态管理
service_ctl() {
    case "$1" in
        start)   systemctl start $2 ;;
        stop)    systemctl stop $2 ;;
        restart) systemctl restart $2 ;;
        *)       echo "用法: $0 {start|stop|restart} <服务名>"
    esac
}

service_ctl restart nginx

五、最佳实践与调试
1. 错误处理
safe_delete() {
    local file="$1"
    if [[ ! -e "$file" ]]; then
        echo "错误:文件不存在" >&2
        return 1
    fi
    rm -f "$file" || return $?
}
2. 调试技巧
# 显示函数调用栈
debug_func() {
    echo "函数名: ${FUNCNAME[0]}"
    echo "调用者: ${FUNCNAME[1]}"
}

# 使用 trap 追踪
trap 'echo "正在执行: ${FUNCNAME[0]}"' DEBUG
3. 性能优化
# 避免频繁调用外部命令
fast_sum() {
    local sum=0
    while read num; do
        ((sum += num))
    done
    echo $sum
}

# 使用管道批量处理
seq 100 | fast_sum   # 输出:5050

六、注意事项
  1. 避免命名冲突:函数名不要与内置命令重复
  2. 参数验证:始终检查输入合法性
  3. 资源释放:在函数结束时清理临时文件
  4. 跨脚本调用:通过 source 或 . 加载函数库

通过合理使用函数,可以实现:
✅ 代码复用率提升
✅ 脚本可维护性增强
✅ 复杂任务模块化分解

建议结合 help function 和 man bash 深入学习高级特性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩瀚之水_csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值