8.5 函数

本教学实验手册介绍了如何在Bash脚本中定义和使用函数,包括基本格式、函数参数的传递和使用。通过示例展示了如何避免代码重复,提高可维护性,并提供了多参数函数的练习,最后通过一个王者荣耀英雄技能模拟器的综合作业,帮助理解脚本参数和函数参数的区别与使用。

在日常编程中,我们经常需要重复使用某段代码。为了避免代码重复编写,提高代码的可维护性,Shell脚本提供了函数(function)功能。

在Bash脚本中,函数的基本格式如下:

bash

function 函数名() {
	# 函数体
}
说明
  • function关键字可以省略,但建议保留以提高代码可读性
  • 函数必须先定义后使用(重要)
  • 函数名要符合标识符命名规范,建议使用有意义的英文名称

让我们来看一个简单的函数使用示例:

bash

#!/bin/bash
# 脚本名:func01.sh

function print_choice() {
	echo -n "你的选择是:" # -n参数不换行
}

echo "这个脚本将显示你的选择"

case $1 in 
	"one")
		print_choice; echo $1 
		;;
	"two")
		print_choice; echo $1 
		;;
	"three")
		print_choice; echo $1 
		;;
	*)
		echo "使用方法:$0 {one|two|three}"
		;;
esac
代码说明
  1. 定义了一个名为print_choice的函数,用于打印固定的提示文字
  2. case语句的每个分支中都调用了这个函数
  3. 通过这种方式,我们避免了重复编写echo语句
  4. -n参数使echo命令输出后不换行,这样后续的内容会接在同一行

运行结果:

从上面的例子中可以看出,当一段代码会被多次使用时,将这段代码放进一个函数内是非常合适的选择。

和普通Shell脚本一样,函数也可以接收参数。在函数中使用参数的方式与脚本参数完全相同:

  • $1 表示第一个参数
  • $2 表示第二个参数
  • 以此类推…

下面是一个使用函数参数的改进版本:

bash

#!/bin/bash
# 脚本名:func02.sh

function print_choice() {
	echo "你的选择是:$1" # -n参数不换行
}

echo "这个脚本将显示你的选择"

case $1 in 
	"one")
		print_choice 1 
		;;
	"two")
		print_choice 2 
		;;
	"three")
		print_choice 3 
		;;
	*)
		echo "使用方法:$0 {one|two|three}"
		;;
esac
改进说明
  1. 函数print_choice现在接收一个参数
  2. 在函数内通过$1访问这个参数
  3. 调用函数时直接在函数名后面跟上参数值
  4. 这样使函数更加灵活,可以显示不同的选择结果

运行结果:

注意事项
  • 函数的参数与脚本的参数是独立的
  • 在函数内部,$1代表传递给函数的第一个参数,而不是脚本的第一个参数
  • 调用函数时参数之间用空格分隔

假设我们需要管理学生的考试成绩,设计一个函数来计算每个学生的平均分并给出评级。这个练习既实用,又能很好地展示多参数函数的应用。

bash

#!/bin/bash
# 文件名:grade_manager.sh

# 函数:计算平均分并评级
function calc_grade() {
    # 接收四个参数:学生姓名、语文分数、数学分数
    student_name=$1
    chinese=$2
    math=$3
    
    # 计算平均分
    local average=$(( ($chinese + $math) / 2 ))
    
    # 根据平均分确定等级
    if [ $average -ge 90 ]; then
        level="优秀"
    elif [ $average -ge 80 ]; then
        level="良好"
    elif [ $average -ge 70 ]; then
        level="中等"
    elif [ $average -ge 60 ]; then
        level="及格"
    else
        level="不及格"
    fi
    
    # 输出结果
    echo "学生:$student_name"
    echo "语文:$chinese"
    echo "数学:$math"
    echo "平均分:$average"
    echo "评级:$level"
    echo "------------------------"
}

# 主程序
echo "==== 学生成绩管理系统 ===="

# 调用函数计算多个学生的成绩
calc_grade "张三" 85 92 
calc_grade "李四" 76 83 
calc_grade "王五" 92 95 
代码说明
  1. 函数calc_grade接收4个参数:
    • $1:学生姓名
    • $2:语文成绩
    • $3:数学成绩
    • $4:英语成绩
  2. 使用算术运算$(( ))计算平均分
  3. 使用if-elif结构判断成绩等级:
  4. 最后格式化输出所有信息

运行结果:

作业目的
通过制作一个简单的技能伤害计算器,理解 Shell 脚本的基本语法和参数使用。

bash

#!/bin/bash
# 文件名:skill_damage.sh

# 计算技能伤害的函数
# 参数:$1-技能伤害 $2-法术攻击 $3-魔抗值
function calc_damage() {
	# 获取参数
    skill_damage=$1   # 技能基础伤害
    magic_attack=$2   # 法术攻击力
    magic_defense=$3  # 魔法防御值
    
    # 计算最终伤害
    final_damage=$(( (skill_damage + magic_attack) * (1000 - magic_defense) / 1000 ))
    
    # 返回计算结果
    echo $final_damage
}

# 检查参数数量
if [ $# -ne 3 ]; then
    echo "使用方法: ./skill_damage.sh 英雄名称 法术攻击 魔抗值"
    echo "例如: ./skill_damage.sh 王昭君 500 200"
    exit 1
fi

# 获取参数
hero=$1      # 英雄名称
magic=$2     # 法术攻击
defense=$3   # 魔抗值

echo "=== 王者荣耀伤害计算器 ==="
echo "英雄:$hero"
echo "法术攻击:$magic"
echo "敌方魔抗:$defense"
echo "======================="

# 计算并显示技能伤害
case $hero in
    "王昭君")
        damage=$(calc_damage 400 $magic $defense)
        echo "凛冬已至:$damage"
        ;;
    "妲己")
        damage=$(calc_damage 450 $magic $defense)
        echo "偶像魅力:$damage"
        ;;
    "安琪拉")
        damage=$(calc_damage 500 $magic $defense)
        echo "火球术:$damage"
        ;;
    *)
        echo "暂不支持该英雄"
        exit 1
        ;;
esac

作业要求:

  1. 理解并运行上述代码,体会参数的使用方法
  2. 完成以下任务:

bash

# 添加一个判断是否击杀的函数
# 参数:$1-造成的伤害 $2-目标血量
function check_kill() {
    # 请补充代码:
    # 1. 如果伤害大于血量,显示"击杀成功!"
    # 2. 否则显示"还需要xx点伤害"
}

# 在主程序调用这个函数测试
check_kill $damage 600

运行结果示例:

相关内容