在 Bash 中处理 GPA 计算脚本中的重复课程

问题描述 投票:0回答:1

我正在编写一个 Bash 脚本来计算学生的 GPA,同时考虑到可能重复的课程。我的目标是确保如果学生重修课程,则 GPA 计算中仅考虑最新成绩。此外,我想排除没有成绩的科目,因为这些科目代表当前正在进行的课程。

我使用的是 Bash 版本 5,因此我可以使用关联数组,并且我尝试利用它们来跟踪每门课程的最新尝试。

但是,我的脚本没有按预期运行——它考虑了重复课程的两次尝试,而不仅仅是最新的一次。以下是我的脚本的相关部分:

#!/bin/bash

# Define a function to convert grades to points
grade_to_points() {
  case $1 in
    A) echo 4 ;;
    A-) echo 3.7 ;;
    B+) echo 3.3 ;;
    B) echo 3 ;;
    B-) echo 2.7 ;;
    C+) echo 2.3 ;;
    C) echo 2 ;;
    D) echo 1 ;;
    F) echo 0 ;;
    *) echo -1 ;; # for subjects with no grade
  esac
}

# Extract the list of subject files and student IDs
subject_files=()
student_ids=()
read_subjects=true
for arg in "$@"; do
  if [[ $arg == "student" ]]; then
    read_subjects=false
    continue
  fi
  if $read_subjects; then
    subject_files+=($arg)
  else
    student_ids+=($arg)
  fi
done

# Loop through each student ID to generate the transcript
for student_id in "${student_ids[@]}"; do
  # Get the student's name from student.dat
  student_name=$(grep "^$student_id" student.dat | cut -d ' ' -f 2-)
  echo "Transcript for $student_id $student_name"
  
  total_points=0
  subjects_count=0
  
  # Loop through each subject file to find grades for the student
  for subject_file in "${subject_files[@]}"; do
    if grep -q "^$student_id" $subject_file; then
      # Extract subject details and grade
      subject_code=$(head -n 1 $subject_file | cut -d ' ' -f 2)
      academic_year=$(head -n 1 $subject_file | cut -d ' ' -f 3)
      semester=$(head -n 1 $subject_file | cut -d ' ' -f 4)
      grade=$(grep "^$student_id" $subject_file | awk '{print ($2=="") ? "" : $2}')
      
      # Print subject details
      echo "$subject_code $academic_year Sem $semester $grade"
      
      # Calculate GPA if grade is present
      if [[ $grade != "" ]]; then
        points=$(grade_to_points $grade)
        if [[ $points != -1 ]]; then
          total_points=$(echo "$total_points + $points" | bc)
          ((subjects_count++))
        fi
      fi
    fi
  done
  
  # Calculate and print GPA if there are graded subjects
  if [[ $subjects_count -gt 0 ]]; then
    gpa=$(echo "scale=2; $total_points / $subjects_count" | bc)
    echo "GPA for $subjects_count subjects $gpa"
  else
    echo "No graded subjects found."
  fi
  echo # New line for separation
done

我得到的输入输出错误:

transcript COMP* student 1236 1234 1223
Transcript for 1236 peter
COMP1011 2021 Sem 2 A
COMP2411 2022 Sem 1 A
COMP2432 2022 Sem 2 
GPA for 2 subjects 4.00

Transcript for 1234 john
COMP1011 2021 Sem 2 B
COMP2411 2022 Sem 1 B-
GPA for 2 subjects 2.85

Transcript for 1223 bob
COMP1011 2021 Sem 2 F
COMP1011 2022 Sem 1 B
COMP2411 2022 Sem 1 C+
COMP2432 2022 Sem 2 
GPA for 3 subjects 1.76

我应该得到输入的正确输出:

transcript COMP* student 1236 1234 1223
Transcript for 1236 peter
COMP1011 2021 Sem 2 A
COMP2411 2022 Sem 1 A
COMP2432 2022 Sem 2
GPA for 2 subjects 4.00

Transcript for 1234 john
COMP1011 2021 Sem 2 B
COMP2411 2022 Sem 1 B
GPA for 2 subjects 2.85

Transcript for 1223 bob
COMP1011 2021 Sem 2 F
COMP1011 2022 Sem 1 B
COMP2411 2022 Sem 1 C+
COMP2432 2022 Sem 2
GPA for 2 subjects 2.65

我使用的文件和内容:

student.dat

1223 bob
1224 kevin
1225 stuart
1226 otto
1234 john
1235 mary
1236 peter
1237 david
1238 alice

COMP101121S2.dat

Subject COMP1011 2021 2
1223 F
1234 B
1235 B+
1236 A

COMP101122S1.dat 

Subject COMP1011 2022 1
1223 B
1224 B+
1225 B1238 C+

COMP241122S1.dat 

Subject COMP2411 2022 1
1223 C+
1234 B1235 B
1236 A

COMP243222S2.dat

Subject COMP2432 2022 2
1223
1235
1236
1237

这是我尝试过的:

  1. 使用关联数组来跟踪每门课程的最新尝试。不幸的是,这似乎没有按预期工作。

  2. 确保我的 Bash 版本支持关联数组,自从我使用版本 5 以来它就支持关联数组。

我的要求是:

  1. 如果学生未及格并重修同一科目,则在 GPA 计算中仅考虑最新成绩。

  2. 如果存在重考,则忽略不及格成绩,但如果没有重考,则将其包括在内。

  3. 不要计算没有成绩的科目,因为它们代表正在进行的课程。

任何人都可以建议如何修改我的脚本以满足这些要求吗?任何帮助将不胜感激!

bash scripting associative-array
1个回答
0
投票

以下是如何使用 awk 执行此操作的起点:

$ cat tst.sh
#!/usr/bin/env bash

awk '
    function grade_to_points(grade,     grade2pts,dfltPts) {
        grade2pts["A"]  = 4
        grade2pts["A-"] = 3.7
        grade2pts["B+"] = 3.3
        grade2pts["B"]  = 3
        grade2pts["B-"] = 2.7
        grade2pts["C+"] = 2.3
        grade2pts["C"]  = 2
        grade2pts["D"]  = 1
        grade2pts["F"]  = 0
        dfltPts         = -1 # for subjects with no grade

        return ( grade in grade2pts ? grade2pts[grade] : dfltPts )
    }

    NR == FNR {
        studId = $1
        studName = gensub(/^\S+\s+/,"",1)
        studId2Name[studId] = studName
        next
    }
    FNR == 1 {
        courseSubj = $2
        courseYear = $3
        courseSem  = $4
        next
    }
    {
        studId = $1
        grade = $2
        studIdCourseSubjYearSem2Grade[studId][courseSubj][courseYear][courseSem] = grade
    }
    END {
        PROCINFO["sorted_in"] = "@ind_str_asc"
        for ( id in studIdCourseSubjYearSem2Grade ) {
            totPoints = totSubjs = 0
            print "Transcript for", id, studId2Name[id]
            for ( subj in studIdCourseSubjYearSem2Grade[id] ) {
                totSubjs ++
                for ( year in studIdCourseSubjYearSem2Grade[id][subj] ) {
                    for ( sem in studIdCourseSubjYearSem2Grade[id][subj][year] ) {
                        grade = studIdCourseSubjYearSem2Grade[id][subj][year][sem]
                        totPoints += grade_to_points(grade)
                        print subj, year, "Sem", sem, grade
                    }
                }
            }
            printf "GPA for %d subjects %0.2f\n\n", totSubjs, (totSubjs ? totPoints / totSubjs : 0)
        }
    }
' student.dat COMP101121S2.dat COMP101122S1.dat COMP241122S1.dat COMP243222S2.dat

$ ./tst.sh
Transcript for 1223 bob
COMP1011 2021 Sem 2 F
COMP1011 2022 Sem 1 B
COMP2411 2022 Sem 1 C+
COMP2432 2022 Sem 2
GPA for 3 subjects 1.43

Transcript for 1224 kevin
COMP1011 2022 Sem 1 B+
GPA for 1 subjects 3.30

Transcript for 1225 stuart
COMP1011 2022 Sem 1 B
GPA for 1 subjects 3.00

Transcript for 1234 john
COMP1011 2021 Sem 2 B
COMP2411 2022 Sem 1 B
GPA for 2 subjects 3.00

Transcript for 1235 mary
COMP1011 2021 Sem 2 B+
COMP2411 2022 Sem 1 B
COMP2432 2022 Sem 2
GPA for 3 subjects 1.77

Transcript for 1236 peter
COMP1011 2021 Sem 2 A
COMP2411 2022 Sem 1 A
COMP2432 2022 Sem 2
GPA for 3 subjects 2.33

Transcript for 1237 david
COMP2432 2022 Sem 2
GPA for 1 subjects -1.00

Transcript for 1238 alice
COMP1011 2022 Sem 1 C+
GPA for 1 subjects 2.30

如果重考,它不会执行您想要的忽略不及格成绩的操作,但希望您会发现上述内容比现有的 bash 脚本更容易理解和修改以执行您想做的任何操作。

© www.soinside.com 2019 - 2024. All rights reserved.