主题
Shell函数定义和调用
课程介绍
函数是编程语言的重要概念,Shell脚本通过函数实现代码复用和模块化。本课程将详细讲解Shell函数的定义、调用、参数传递、返回值等核心概念,帮助你掌握Shell脚本中的函数编程。
1. 函数概述
1.1 什么是函数
函数是一段可重复使用的代码块,可以接受参数并返回结果。
函数的优势:
- 代码复用:避免重复编写相同代码
- 模块化:将复杂逻辑分解为多个函数
- 可读性:提高代码可读性
- 维护性:便于维护和修改
1.2 函数的基本语法
Shell函数有两种定义语法。
语法1:使用function关键字
bash
function 函数名 {
代码块
}语法2:不使用function关键字
bash
函数名() {
代码块
}2. 函数定义和调用
2.1 定义函数
定义函数的两种方式。
示例1:使用function关键字
bash
#!/bin/bash
# 定义函数
function say_hello {
echo "Hello, World!"
}
# 调用函数
say_hello示例2:不使用function关键字
bash
#!/bin/bash
# 定义函数
say_hello() {
echo "Hello, World!"
}
# 调用函数
say_hello2.2 调用函数
调用函数非常简单,直接使用函数名即可。
示例:
bash
#!/bin/bash
# 定义函数
function greet {
echo "Hello, $1!"
}
# 调用函数
greet "张三"
greet "李四"3. 函数参数
3.1 传递参数
函数可以接受参数,使用$1、$2、$3等引用参数。
示例1:传递单个参数
bash
#!/bin/bash
# 定义函数
function greet {
echo "Hello, $1!"
}
# 调用函数
greet "张三"示例2:传递多个参数
bash
#!/bin/bash
# 定义函数
function add {
sum=$(($1 + $2))
echo "$1 + $2 = $sum"
}
# 调用函数
add 10 20
add 30 40示例3:传递所有参数
bash
#!/bin/bash
# 定义函数
function print_args {
echo "参数个数:$#"
echo "所有参数:$@"
echo "第一个参数:$1"
echo "第二个参数:$2"
}
# 调用函数
print_args "张三" "李四" "王五"3.2 参数引用
函数参数的引用方式。
| 参数 | 说明 |
|---|---|
$0 | 函数名 |
$1~$9 | 第1~9个参数 |
$# | 参数个数 |
$@ | 所有参数(每个参数独立引用) |
$* | 所有参数(作为整体引用) |
示例:
bash
#!/bin/bash
# 定义函数
function show_params {
echo "函数名:$0"
echo "参数个数:$#"
echo "所有参数($@):$@"
echo "所有参数($*):$*"
echo "第一个参数:$1"
echo "第二个参数:$2"
}
# 调用函数
show_params "张三" "李四" "王五"4. 函数返回值
4.1 返回状态码
函数可以返回状态码(0-255),0表示成功,非0表示失败。
示例:
bash
#!/bin/bash
# 定义函数
function check_file {
if [ -f "$1" ]; then
return 0
else
return 1
fi
}
# 调用函数
check_file "/etc/passwd"
echo "返回值:$?"
check_file "/nonexistent"
echo "返回值:$?"4.2 返回字符串
函数不能直接返回字符串,但可以通过echo输出字符串。
示例1:使用echo返回字符串
bash
#!/bin/bash
# 定义函数
function get_date {
echo $(date +%Y-%m-%d)
}
# 调用函数
today=$(get_date)
echo "今天是:$today"示例2:使用变量返回字符串
bash
#!/bin/bash
# 定义函数
function get_date {
RESULT=$(date +%Y-%m-%d)
}
# 调用函数
get_date
echo "今天是:$RESULT"5. 函数作用域
5.1 全局变量
全局变量在函数内外都可以访问。
示例:
bash
#!/bin/bash
# 定义全局变量
global_var="全局变量"
# 定义函数
function show_var {
echo "函数内:$global_var"
global_var="函数内修改"
}
# 调用函数
show_var
echo "函数外:$global_var"5.2 局部变量
局部变量只在函数内有效,使用local关键字定义。
示例:
bash
#!/bin/bash
# 定义全局变量
global_var="全局变量"
# 定义函数
function show_var {
local local_var="局部变量"
echo "函数内:$global_var"
echo "函数内:$local_var"
}
# 调用函数
show_var
echo "函数外:$global_var"
echo "函数外:$local_var" # 输出为空6. 函数库
6.1 创建函数库
将常用函数定义在一个文件中,作为函数库。
示例:
bash
# 文件:functions.sh
# 函数:检查文件是否存在
function check_file {
if [ -f "$1" ]; then
return 0
else
return 1
fi
}
# 函数:检查目录是否存在
function check_dir {
if [ -d "$1" ]; then
return 0
else
return 1
fi
}
# 函数:创建备份
function backup_file {
local file=$1
local backup="${file}.bak"
cp "$file" "$backup"
echo "备份文件:$file -> $backup"
}6.2 使用函数库
使用source或.命令加载函数库。
示例:
bash
#!/bin/bash
# 加载函数库
source ./functions.sh
# 使用函数库中的函数
check_file "/etc/passwd"
if [ $? -eq 0 ]; then
echo "文件存在"
else
echo "文件不存在"
fi
backup_file "/etc/passwd"7. 完整示例
示例1:用户管理函数库
bash
#!/bin/bash
# 用户管理函数库
# 函数:创建用户
function create_user {
local username=$1
local password=$2
# 检查用户是否已存在
if id "$username" &>/dev/null; then
echo "用户 $username 已存在"
return 1
fi
# 创建用户
useradd "$username"
# 设置密码
echo "$username:$password" | chpasswd
echo "用户 $username 创建成功"
return 0
}
# 函数:删除用户
function delete_user {
local username=$1
# 检查用户是否存在
if ! id "$username" &>/dev/null; then
echo "用户 $username 不存在"
return 1
fi
# 删除用户
userdel -r "$username"
echo "用户 $username 删除成功"
return 0
}
# 函数:查看用户
function show_user {
local username=$1
# 检查用户是否存在
if ! id "$username" &>/dev/null; then
echo "用户 $username 不存在"
return 1
fi
# 显示用户信息
id "$username"
return 0
}
# 主程序
echo "===== 用户管理 ====="
echo "1. 创建用户"
echo "2. 删除用户"
echo "3. 查看用户"
echo "4. 退出"
echo "=================="
read -p "请选择(1-4):" choice
case $choice in
1)
read -p "请输入用户名:" username
read -s -p "请输入密码:" password
echo ""
create_user "$username" "$password"
;;
2)
read -p "请输入用户名:" username
delete_user "$username"
;;
3)
read -p "请输入用户名:" username
show_user "$username"
;;
4)
echo "退出"
exit 0
;;
*)
echo "选择错误"
exit 1
;;
esac示例2:文件操作函数库
bash
#!/bin/bash
# 文件操作函数库
# 函数:检查文件是否存在
function check_file {
if [ -f "$1" ]; then
return 0
else
return 1
fi
}
# 函数:检查文件权限
function check_permission {
local file=$1
local permission=$2
if [ ! -f "$file" ]; then
echo "文件不存在"
return 1
fi
if [ "$permission" = "read" ]; then
if [ -r "$file" ]; then
return 0
else
return 1
fi
elif [ "$permission" = "write" ]; then
if [ -w "$file" ]; then
return 0
else
return 1
fi
elif [ "$permission" = "execute" ]; then
if [ -x "$file" ]; then
return 0
else
return 1
fi
else
echo "权限类型错误"
return 1
fi
}
# 函数:统计文件行数
function count_lines {
local file=$1
if [ ! -f "$file" ]; then
echo "文件不存在"
return 1
fi
local lines=$(wc -l < "$file")
echo "文件 $file 的行数:$lines"
return 0
}
# 函数:搜索文件内容
function search_file {
local file=$1
local keyword=$2
if [ ! -f "$file" ]; then
echo "文件不存在"
return 1
fi
local count=$(grep -c "$keyword" "$file")
echo "文件 $file 中包含 '$keyword' 的行数:$count"
return 0
}
# 主程序
echo "===== 文件操作 ====="
read -p "请输入文件路径:" file
if ! check_file "$file"; then
echo "文件不存在"
exit 1
fi
count_lines "$file"
read -p "请输入搜索关键词:" keyword
search_file "$file" "$keyword"示例3:系统监控函数库
bash
#!/bin/bash
# 系统监控函数库
# 函数:获取CPU使用率
function get_cpu_usage {
local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
echo "CPU使用率:${cpu_usage}%"
}
# 函数:获取内存使用率
function get_mem_usage {
local mem_usage=$(free | grep Mem | awk '{printf("%.2f", $3/$2 * 100.0)}')
echo "内存使用率:${mem_usage}%"
}
# 函数:获取磁盘使用率
function get_disk_usage {
local disk_usage=$(df -h / | tail -1 | awk '{print $5}' | cut -d'%' -f1)
echo "磁盘使用率:${disk_usage}%"
}
# 函数:获取网络连接数
function get_net_connections {
local connections=$(ss -an | wc -l)
echo "网络连接数:$connections"
}
# 主程序
echo "===== 系统监控 ====="
get_cpu_usage
get_mem_usage
get_disk_usage
get_net_connections
echo "=================="8. 函数最佳实践
8.1 函数命名规范
- 使用小写字母和下划线
- 函数名应该描述函数的功能
- 避免使用Shell关键字
示例:
bash
# 好的函数名
check_file()
backup_file()
send_email()
# 不好的函数名
cf()
bf()
se()8.2 函数注释
为函数添加注释,说明函数的功能、参数、返回值。
示例:
bash
# 函数:检查文件是否存在
# 参数:文件路径
# 返回值:0-文件存在,1-文件不存在
function check_file {
if [ -f "$1" ]; then
return 0
else
return 1
fi
}8.3 函数错误处理
为函数添加错误处理,提高脚本的健壮性。
示例:
bash
# 函数:创建备份
function backup_file {
local file=$1
# 检查文件是否存在
if [ ! -f "$file" ]; then
echo "错误:文件不存在"
return 1
fi
# 创建备份
local backup="${file}.bak"
if ! cp "$file" "$backup"; then
echo "错误:备份失败"
return 1
fi
echo "备份成功:$file -> $backup"
return 0
}课程总结
这节课我们学习了Shell函数定义和调用。
核心内容:
- 函数概述
- 函数定义和调用
- 函数参数
- 函数返回值
- 函数作用域
- 函数库
- 完整示例
- 函数最佳实践
重要概念:
- 函数定义:function name {} 或 name() {}
- 函数调用:直接使用函数名
- 函数参数:$1、$2、$3等
- 函数返回值:return返回状态码,echo返回字符串
- 函数作用域:全局变量和局部变量
函数是Shell脚本编程的重要概念,掌握这些知识后,我们将在后续课程中学习文件操作、字符串处理等高级特性。
课后练习
练习1(基础)
创建一个脚本,要求:
- 定义一个函数,输出"Hello, World!"
- 调用该函数
练习2(进阶)
创建一个脚本,要求:
- 定义一个函数,接受两个参数
- 计算两个参数的和
- 输出结果
练习3(拓展)
创建一个脚本,要求:
- 定义一个函数库,包含以下函数:
- 检查文件是否存在
- 统计文件行数
- 搜索文件内容
- 使用函数库中的函数