函数基础 #
一、函数定义 #
1.1 基本语法 #
bash
# 方式一:使用function关键字
function 函数名() {
命令
}
# 方式二:省略function关键字
函数名() {
命令
}
# 方式三:单行定义
函数名() { 命令; }
1.2 简单示例 #
bash
#!/bin/bash
# 定义函数
hello() {
echo "Hello, World!"
}
# 调用函数
hello
# 带参数的函数
greet() {
echo "你好, $1!"
}
greet "张三"
greet "李四"
1.3 函数定义位置 #
bash
#!/bin/bash
# 函数必须先定义后使用
# 错误示例:
# hello # 此时函数未定义,会报错
# 正确示例:
hello() {
echo "Hello!"
}
hello # 正确调用
# 函数可以放在脚本开头或单独文件中
二、函数调用 #
2.1 基本调用 #
bash
#!/bin/bash
show_info() {
echo "当前用户: $USER"
echo "当前目录: $(pwd)"
echo "当前时间: $(date)"
}
# 直接调用
show_info
# 在命令替换中调用
info=$(show_info)
echo "$info"
# 在条件中调用
if show_info; then
echo "函数执行成功"
fi
2.2 在其他脚本中调用 #
bash
#!/bin/bash
# functions.sh - 函数库文件
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
error() {
echo "[ERROR] $*" >&2
}
bash
#!/bin/bash
# main.sh - 主脚本
source functions.sh # 加载函数库
log "程序启动"
error "发生错误"
三、函数参数 #
3.1 位置参数 #
bash
#!/bin/bash
# 函数参数使用位置参数
show_args() {
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "所有参数: $@"
echo "参数个数: $#"
}
show_args "apple" "banana" "cherry"
# 输出:
# 第一个参数: apple
# 第二个参数: banana
# 所有参数: apple banana cherry
# 参数个数: 3
3.2 参数处理 #
bash
#!/bin/bash
# 默认参数
greet() {
local name="${1:-匿名}"
echo "你好, $name!"
}
greet "张三" # 输出: 你好, 张三!
greet # 输出: 你好, 匿名!
# 参数验证
process_file() {
local file="$1"
if [[ -z "$file" ]]; then
echo "错误: 请指定文件名" >&2
return 1
fi
if [[ ! -f "$file" ]]; then
echo "错误: 文件 $file 不存在" >&2
return 1
fi
echo "处理文件: $file"
# 处理逻辑
}
process_file "test.txt"
3.3 遍历参数 #
bash
#!/bin/bash
# 遍历所有参数
print_all() {
for arg in "$@"; do
echo "参数: $arg"
done
}
print_all "one" "two" "three"
# 使用shift处理参数
process_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
-f|--file)
file="$2"
shift 2
;;
-v|--verbose)
verbose=true
shift
;;
*)
echo "未知参数: $1"
shift
;;
esac
done
echo "文件: ${file:-未指定}"
echo "详细模式: ${verbose:-false}"
}
process_args -f test.txt -v
四、函数返回值 #
4.1 使用return #
bash
#!/bin/bash
# 返回状态码
is_even() {
local num=$1
if (( num % 2 == 0 )); then
return 0 # 成功
else
return 1 # 失败
fi
}
# 使用返回值
if is_even 10; then
echo "10是偶数"
fi
if ! is_even 7; then
echo "7不是偶数"
fi
# 获取返回值
is_even 10
echo "返回值: $?" # 输出: 0
4.2 使用echo返回 #
bash
#!/bin/bash
# 返回字符串
get_full_name() {
local first="$1"
local last="$2"
echo "$first $last"
}
name=$(get_full_name "张" "三")
echo "全名: $name"
# 返回计算结果
add() {
local a=$1
local b=$2
echo $((a + b))
}
result=$(add 5 3)
echo "结果: $result"
# 返回数组
get_numbers() {
echo "1 2 3 4 5"
}
numbers=($(get_numbers))
echo "数组: ${numbers[@]}"
4.3 返回多个值 #
bash
#!/bin/bash
# 方式一:使用全局变量
get_user_info() {
user_name="张三"
user_age=25
user_city="北京"
}
get_user_info
echo "姓名: $user_name"
echo "年龄: $user_age"
echo "城市: $user_city"
# 方式二:使用echo返回多行
get_user_info2() {
echo "张三"
echo "25"
echo "北京"
}
read -r name age city <<< "$(get_user_info2)"
echo "姓名: $name, 年龄: $age, 城市: $city"
# 方式三:使用关联数组
get_user_info3() {
declare -A user
user[name]="张三"
user[age]=25
user[city]="北京"
# 返回键值对
for key in "${!user[@]}"; do
echo "$key=${user[$key]}"
done
}
declare -A result
while IFS='=' read -r key value; do
result[$key]="$value"
done < <(get_user_info3)
echo "姓名: ${result[name]}"
五、局部变量 #
5.1 使用local关键字 #
bash
#!/bin/bash
# 全局变量
global_var="全局变量"
test_scope() {
# 局部变量
local local_var="局部变量"
echo "函数内 - 全局: $global_var"
echo "函数内 - 局部: $local_var"
# 修改全局变量
global_var="修改后的全局变量"
}
test_scope
echo "函数外 - 全局: $global_var"
echo "函数外 - 局部: $local_var" # 空值
5.2 变量作用域示例 #
bash
#!/bin/bash
count=0
increment() {
local count=10
((count++))
echo "函数内 count: $count"
}
increment # 输出: 11
echo "函数外 count: $count" # 输出: 0
# 使用全局变量
increment_global() {
((count++))
echo "函数内 count: $count"
}
increment_global # 输出: 1
echo "函数外 count: $count" # 输出: 1
六、实战示例 #
6.1 日志函数 #
bash
#!/bin/bash
# 日志级别
LOG_LEVEL=0 # 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR
log() {
local level="$1"
shift
local message="$*"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local level_num
case "$level" in
DEBUG) level_num=0 ;;
INFO) level_num=1 ;;
WARN) level_num=2 ;;
ERROR) level_num=3 ;;
*) level_num=1 ;;
esac
if [ $level_num -ge $LOG_LEVEL ]; then
echo "[$timestamp] [$level] $message"
fi
}
log DEBUG "调试信息"
log INFO "普通信息"
log WARN "警告信息"
log ERROR "错误信息"
6.2 文件处理函数 #
bash
#!/bin/bash
# 检查文件
check_file() {
local file="$1"
[[ -z "$file" ]] && { echo "错误: 文件名为空"; return 1; }
[[ ! -e "$file" ]] && { echo "错误: 文件不存在"; return 1; }
[[ ! -f "$file" ]] && { echo "错误: 不是普通文件"; return 1; }
[[ ! -r "$file" ]] && { echo "错误: 文件不可读"; return 1; }
return 0
}
# 读取文件内容
read_file() {
local file="$1"
check_file "$file" || return 1
while IFS= read -r line; do
echo "$line"
done < "$file"
}
# 写入文件
write_file() {
local file="$1"
local content="$2"
echo "$content" > "$file"
}
# 追加内容
append_file() {
local file="$1"
local content="$2"
echo "$content" >> "$file"
}
6.3 数学计算函数 #
bash
#!/bin/bash
# 加法
add() {
echo $(($1 + $2))
}
# 减法
subtract() {
echo $(($1 - $2))
}
# 乘法
multiply() {
echo $(($1 * $2))
}
# 除法
divide() {
if (( $2 == 0 )); then
echo "错误: 除数不能为0" >&2
return 1
fi
echo $(($1 / $2))
}
# 计算器
calculate() {
local a=$1
local op=$2
local b=$3
case "$op" in
+) add $a $b ;;
-) subtract $a $b ;;
\*) multiply $a $b ;;
/) divide $a $b ;;
*) echo "未知运算符: $op" ;;
esac
}
result=$(calculate 10 + 5)
echo "结果: $result"
七、函数最佳实践 #
7.1 命名规范 #
bash
#!/bin/bash
# 推荐:使用小写字母和下划线
get_user_info() { ... }
calculate_total() { ... }
process_file() { ... }
# 不推荐:使用大写字母
GET_USER_INFO() { ... }
# 推荐:函数名描述功能
check_file_exists() { ... }
validate_input() { ... }
send_notification() { ... }
7.2 函数注释 #
bash
#!/bin/bash
# 函数:获取用户信息
# 参数:
# $1 - 用户ID
# 返回:
# 用户信息字符串
# 示例:
# get_user_info 123
get_user_info() {
local user_id="$1"
# 函数实现
}
# 使用here document写注释
: << 'EOF'
函数:计算总价
参数:
$1 - 单价
$2 - 数量
返回:总价
EOF
calculate_total() {
local price="$1"
local quantity="$2"
echo $((price * quantity))
}
7.3 错误处理 #
bash
#!/bin/bash
# 使用set -e和返回值
process_data() {
local file="$1"
# 验证输入
if [[ -z "$file" ]]; then
echo "错误: 文件名为空" >&2
return 1
fi
# 检查文件
if [[ ! -f "$file" ]]; then
echo "错误: 文件不存在: $file" >&2
return 1
fi
# 处理文件
if ! grep -q "pattern" "$file"; then
echo "警告: 未找到匹配模式" >&2
return 2
fi
return 0
}
# 调用并处理错误
if ! process_data "test.txt"; then
echo "处理失败"
exit 1
fi
八、总结 #
8.1 函数要点 #
| 要点 | 说明 |
|---|---|
| 定义 | 函数名() |
| 调用 | 直接使用函数名 |
| 参数 | 使用$1, $2, $@, $# |
| 返回值 | return返回状态码,echo返回数据 |
| 局部变量 | 使用local关键字 |
8.2 下一步 #
你已经掌握了函数基础,接下来让我们学习 函数参数,深入了解参数传递!
最后更新:2026-03-27