免责声明:学生作品,水平有限,有问题请自行百度,谢谢
1. Linux下基于Shell脚本,编写简单的学生成绩管理系统,系统分为教师模块、学生模块。主要功能为教师通过系统添加、修改、删除、查看学生成绩;学生可查看成绩。该学生成绩管理系统的具体功能如下:
- 系统允许教师或学生登录
- 系统允许教师添加学生成绩,实现各科分数求和
- 系统允许教师修改学生成绩,修改成绩时自动更新总分
- 系统允许教师删除学生成绩
- 系统允许教师、学生查看成绩
- 退出系统
- 实验步骤
- 利用hostnamectl命令将主机名修改为自己的名字:
hostnamectl set-hostname studentName // studentName是自己的名字
- 创建3个学生用户(stu1、stu2、stu3)和2个教师用户(tea1、tea2),学生用户属于student用户组,教师用户属于teacher用户组,并建立学生现有成绩数据集。
-
步骤 1: 创建用户组
打开终端或命令行界面,并使用以下命令创建用户组:
-
sudo groupadd student sudo groupadd teacher
-
步骤 2: 创建学生用户并添加到student用户组
接下来,我们将创建三个学生用户,并将它们添加到
student
用户组:这里的
-m
选项告诉useradd
为用户创建家目录(通常位于/home/用户名
),-g
选项指定用户的初始登录组。 -
sudo useradd -g student stu1
sudo useradd -g student stu2 s
udo useradd -g student stu3
步骤 3: 创建教师用户并添加到teacher用户组类似地,我们将创建两个教师用户,并将它们添加到
teacher
用户组: -
sudo useradd -g teacher tea1
sudo useradd -g teacher tea2
验证你可以通过查看
/etc/group
文件来验证用户是否已正确添加到相应的用户组中: - grep student /etc/group
- grep teacher /etc/group
- 设计学生成绩管理系统,具体要求如下:
A、进入系统后需先登录系统,主界面如下:
----------------------------欢迎使用学生成绩管理系统------------------------------
* 1、学生身份登录系统 *
* 2、教师身份登录系统 *
* 3、退出学生成绩管理系统 *
----------------------------------------------------------------------------------------
- 如以学生身份登录系统,系统显示的主界面如下:
----------------------欢迎使用学生成绩管理系统(学生)------------------------
* 1、学生查看成绩 *
* 2、学生退出系统 *
----------------------------------------------------------------------------------------
C、如以教师身份登录系统,系统显示的主界面如下:
----------------------欢迎使用学生成绩管理系统(教师)------------------------
* 1、教师添加成绩 *
* 2、教师修改成绩 *
* 3、教师删除成绩 *
* 4、教师查看成绩 *
* 0、教师退出系统 *
----------------------------------------------------------------------------------------
#! /bin/bash
#数据存储文件
DATA_FILE="grades.txt"
#每行遵循用户名,课程,成绩
#登陆界面
function show_menu {
#缩进只是为了代码可读性
clear
echo "------------欢迎使用学生成绩管理系统---------------------------"
echo "* 1、学生身份登陆系统 *"
echo "* 2、教师身份登陆系统 *"
echo "* 3、退出学生成绩管理系统 *"
echo "--------------------------------------------"
read -p "请输入(1/2/3):" choice
#-p显示提示信息 choice表示变量
case $choice in
1) student_login ;;#按1
2) teacher_login ;;#按2
3) exit 0 ;;
*) echo "无效输入,重新输入"; show_menu ;;
#结束标志
#结束登录界面
#缩进是为了美观
esac
}
#学生登录界面
function student_login {
read -p "请输入你的学号:" username # 获取用户输入的学号作为用户名
# 检查用户名是否存在
if grep -q "^$username," grades.txt; then
student_menu $username # 调用学生菜单函数,将学号作为参数传递
else
echo "无效的用户名,请重新输入!"
student_login # 重新调用登录函数,实现循环登录
fi
}
#学生功能菜单
function student_menu {
local username=$1 # 使用传入的参数作为学号,并存储在局部变量中
while true; do
clear # 清屏,清除终端中的内容
echo "-------欢迎使用学生成绩管理系统(学生)-----------"
echo "* 1、学生查看成绩 *" # 提供学生查看成绩的选项
echo "* 2、学生退出系统 *" # 提供学生退出系统的选项
echo "---------------------------------------------"
read -p "请输入(1/2):" choice # 获取用户输入的选项
case $choice in
1) view_grades $username ;; # 如果用户输入1,调用查看成绩函数,并将学号作为参数传递
2) show_menu ;; # 如果用户输入2,返回主菜单
*) echo "无效输入,重新输入" ;; # 如果用户输入无效选项,输出提示信息
esac
done
}
#教师登录
function teacher_login {
read -p "请输入教师号:" username # 获取用户输入的教师号作为用户名
if [[ "$username" == "tea1" || "$username" == "tea2" ]]; then
teacher_menu $username # 如果用户名是有效的,则调用教师菜单函数,并将教师号作为参数传递
else
echo "无效用户名,请重新输入!" # 如果用户名无效,输出提示信息
teacher_login # 重新调用登录函数,实现循环登录
fi
}
#教师功能菜单
function teacher_menu {
local username=$1
while true; do
clear
echo "----------欢迎使用教师功能菜单-----------------------"
echo "* 1、教师添加成绩 *"
echo "* 2、教师修改成绩 *"
echo "* 3、教师删除成绩 *"
echo "* 0、教师退出 *"
echo "* 4、教师查看成绩 *"
echo "----------------------------------------"
read -p "请输入(1/2/3/4/0):" choice
case $choice in
1) add_grade $username ;;
#按1
2) edit_grade $username ;;
#按2
3) delete_grade $username ;;
#按3
4) view_local_grade ;;
#按4
0) show_menu ;;
#按0
*) echo "无效输入,请重新输入";;
esac
done
}
# 添加成绩
function add_grade {
read -p "请输入学生用户名:" stu_username # 获取用户输入的学生用户名
read -p "请输入课程名称:" course # 获取用户输入的课程名称
read -p "请输入成绩:" score # 获取用户输入的成绩
echo "$stu_username,$course,$score" >> $DATA_FILE # 将学生用户名、课程名称和成绩以逗号分隔的格式写入数据文件末尾
echo "成绩添加成功" # 输出添加成功的提示信息
}
#编辑成绩
# 定义编辑成绩的函数
function edit_grade {
# 定义数据文件名
local DATA_FILE="grades.txt"
# 读取用户输入的学生用户名
read -p "请输入学生用户名:" stu_username
# 读取用户输入的新成绩
read -p "请输入新成绩:" new_score
# 使用 awk 命令查找并替换成绩
# -v 选项用于在 awk 程序中定义变量,这里定义了 user 和 score 变量
awk -v user="$stu_username" -v score="$new_score" '
# BEGIN 块:设置输入字段分隔符 FS 和输出字段分隔符 OFS 为逗号
BEGIN { FS=","; OFS="," }
# 如果当前行的第一个字段(用户名)与 user 变量匹配
$1 == user {
# 替换当前行的第三个字段(成绩)为 score 变量的值
$3 = score;
}
# 打印当前行(无论是否进行了修改)
{ print }
' "$DATA_FILE" > tmp && # 将 awk 的输出重定向到临时文件 tmp,如果成功则执行后面的 mv 命令
mv tmp "$DATA_FILE" # 将临时文件 tmp 替换原数据文件
# 输出提示信息
echo "成绩更新成功"
}
#删除成绩
# 定义删除学生成绩的函数
function delete_grade {
# 定义数据文件名
local DATA_FILE="grades.txt"
# 定义备份文件名,这里实际上后缀是多余的,但为了与DATA_FILE区分,保留
local BACKUP_FILE="${DATA_FILE}.txt"
# 读取用户输入的学生用户名
read -p "请输入学生用户名:" stu_username
# 使用 cp 命令备份原文件,确保在修改前有一个原始文件的副本
cp "$DATA_FILE" "$BACKUP_FILE" && # 备份成功则继续执行后面的命令
# 使用 sed 命令直接修改原文件,删除所有以指定用户名开头的行
# -i 选项表示直接修改文件内容
sed -i "/^${stu_username},/d" "$DATA_FILE" # 删除所有以 stu_username 开头(后面紧跟逗号)的行
# 检查上一个命令(sed)的退出状态
# $? 是一个特殊变量,保存了上一个命令的退出状态
if [ $? -eq 0 ]; then
# 如果 sed 命令成功执行(即 $? 的值为 0),则输出成功消息
echo "记录删除成功"
else
# 如果 sed 命令执行失败(即 $? 的值不为 0),则输出失败消息并恢复原始文件
echo "删除失败,可能未找到指定记录。已恢复原始文件。"
# 使用 mv 命令将备份文件恢复为原文件名,即恢复原始文件
mv "$BACKUP_FILE" "$DATA_FILE"
fi
}
#查看成绩
# 定义查看成绩的函数
function view_grades {
# 接收第一个参数作为用户名
local username=$1
# 检查是否提供了用户名
if [[ -n $username ]]; then
# 如果提供了用户名,则使用 grep 查找包含该用户名的行
# 并通过 while 循环读取每行,假设每行数据以逗号分隔
grep "^$username," "$DATA_FILE" | while IFS=',' read -r stu_username course score; do
# 打印当前行的学生用户名、课程和成绩
echo "学生:$stu_username,课程:$course,成绩: $score"
done
else
# 如果没有提供用户名,则显示所有成绩
echo "未提供用户名,显示所有成绩:"
# 使用 while 循环和重定向从文件中读取每行数据
while IFS=',' read -r stu_username course score; do
# 打印当前行的学生用户名、课程和成绩
echo "学生:$stu_username,课程:$course,成绩: $score"
done < "$DATA_FILE"
fi
# 在所有成绩显示后,等待用户按任意键继续
# 注意:这可能会在某些环境(如脚本直接运行时)中不起作用,因为它会阻塞终端
read -p "按任意键返回" key
}
# 注意:
# 1. 此函数依赖于一个外部变量 $DATA_FILE,它应该在函数外部定义,并指向包含成绩数据的文件。
# 2. `read -p "按任意键返回" key` 可能会在某些脚本执行环境中(如非交互式shell)导致问题,因为它会等待用户输入。
# 3. 如果 $DATA_FILE 的每行数据格式不是严格的 "用户名,课程,成绩" 格式,或者包含额外的逗号,这个脚本可能需要进一步调整。
# 4. 为了提高代码的健壮性,可以考虑添加对 $DATA_FILE 文件存在性和可读性的检查。
#教师查看成绩
# 定义查看本地成绩的函数
function view_local_grade {
# 声明局部变量 stu_username 用于存储用户输入的学生用户名
local stu_username
# 声明并初始化局部变量 DATA_FILE,指定成绩数据文件的路径
local DATA_FILE="grades.txt"
# 提示用户输入要查找的学生的用户名
read -p "请输入查找的学生的用户名:" stu_username
# 检查用户是否提供了用户名
if [[ -n $stu_username ]]; then
# 如果提供了用户名,则使用 grep 命令查找包含该用户名的行
# 并通过管道将结果传递给 while 循环,使用 IFS=',' 设置字段分隔符为逗号
# 在循环中读取每行数据,并分别将用户名、课程和成绩赋值给相应的变量
grep "^$stu_username," "$DATA_FILE" | while IFS=',' read -r stu_username course score; do
# 打印当前行的学生信息,包括用户名、课程和成绩
echo "学生:$stu_username,课程:$course,成绩: $score"
done
else
# 如果用户未提供用户名,则显示所有成绩
echo "未提供用户名,显示所有成绩:"
# 使用 while 循环直接从文件中读取每行数据,并打印
# 注意这里不需要 grep,因为我们要读取所有行
while IFS=',' read -r stu_username course score; do
# 打印当前行的学生信息,包括用户名、课程和成绩
echo "学生:$stu_username,课程:$course,成绩: $score"
done < "$DATA_FILE" # 使用重定向从文件中读取数据
fi
# 在所有成绩显示后,提示用户按任意键继续
# 注意:这将在终端等待用户输入,可能会在某些非交互式环境中造成问题
read -p "按任意键返回" key
}
# 注意:
# 1. 该函数依赖于本地文件 grades.txt 的存在和可访问性。
# 2. 如果用户输入的用户名不存在于文件中,grep 命令将不会输出任何内容,因此也不会显示任何与该用户名相关的成绩。
# 3. 如果 grades.txt 文件的格式不是严格的 "用户名,课程,成绩" 格式,或者包含额外的逗号,这个脚本可能需要进一步调整。
# 4. 在实际应用中,可能还需要添加额外的错误处理,比如检查文件是否存在、用户是否有权访问该文件等。
show_menu