How to compute grades using awk First, make a file called "grades" with your students' scores like the one below. Don't put any spaces in the name. The columns can be separated by a combination of any number of tabs and spaces. I like tabs. The columns do not have to be aligned. (At the end of this article, I list a shell-script program that makes inputting scores easy.) Cantor,G 90 85 76 89 44 Dedekind,G 70 77 70 97 49 Gauss,C 62 77 67 89 39 Kronecker,S 92 100 95 89 45 Riemann,B 95 98 98 93 49 Weierstrass,K 78 89 86 79 45 Now put the following line in a file called "program". {s=$2+$3+$4+$5+$6; print $0 "\t" s} The command awk -f program grades > results takes your "grades" file and applies "program" to each line, one at a time. If you don't put the "> results" on the end, the output goes to the screen. The -f option tells awk to take its instructions from the file called "program" (any name is ok). The output goes to a file called "results". The awk language is very simple. Here is what the program above does: $1, $2, $3, etc. stand for columns 1,2,3, etc., $0 stands for the whole line. s is the sum of the numbers in columns 2 - 6; the program tells awk to print the whole line ($0), followed by a tab ("\t"), followed by the total s. The effect of the program is to create a new file called "results" with a seventh column of numbers which is the total score for each student. Here is another great program: {s=$2+$3+$4+$5+$6; print s "\t" $1} Put that line in a file called "program" and try this one: awk -f program grades | sort -r -n > results What it does is compute a grand total for each student, prints out the total followed by the student's name ($1); then the output is piped to the unix sort command; the -n option tells sort to expect numbers, the -r option tells sort to put the numbers in reverse, i.e., decreasing order. The effect of the program is to spit out a list of your students ranked according to total points into a file called "results." ("\t" puts a tab between the total s and the name in $1.) You can easily alter the programs above to compute weighted sums. For example, let's say that column 6 is the total homework points with a maximum possible of 500 and that you want to rescale it to be a maximum of 100 when you add up the total. Just use {s=$2+$3+$4+$5+$6/5; print s "\t" $1} If you don't like the numbers to the right of the decimal, just use int($6/5+.5) in place of $6/5 to round the number to the nearest integer. Another groovy program: {t+=$6} END {print "ave = " t/NR} The command, awk -f program grades spits out the average of the numbers in column 6. (NR stands for "the number of records in the file" and is equal to the number of lines in the grade file. Make sure you don't have any blank or extra lines in your grades file if you use this command.) Another nice program is: {if($7 >= 487) gr="A" else if ($7 >= 449) gr="B" else if ($7 >= 405) gr="C" else if ($7 >= 348) gr="D" else gr="F" print gr,"\t",$1} If the grand total score of each student is in column 7, the command, awk -f program grades spits out a list of your students with their final grades written to the left of their names (using the obvious cutoffs). If you change the last line of the program to print $0,"\t",gr} you will get a copy of your grades file with the final grades written in a new column 8. awk wiz, Joe Lipman, gives the following tip for transforming a classlist file that you get from Peter Cook into a list of names suitable for grade awking: sed 's/,.*//; s/[^A-Z]//g' classlist > gradelist or sed 's/,.*//' classlist | cut -c 18-30 > gradelist If you like awk, you will love nawk (new awk). Put the lines below (starting at the line with the : above the #-signs) in a file called "input" and then type chmod u+x input to make "input" an executable file. If you keep your grades in a file called "grades," the command input grades will allow you to input scores one by one for the students named in your grades list. The program adds the scores to your "grades" file in a new column and sends the updated results to a new file called "g.out" (it overwrites any file in your current directory called "g.out", so be careful). It leaves your original "grades" file alone. You will be prompted to enter the score for student "x" by student x's name. Enter the score and push . When you have entered a score for each student, the "input" program terminates and you can find the updated grade list in the "g.out" file. (If you use "input" frequently, you will probably want to put it in a directory called bin in your home directory.) If you like what you see in "g.out," you can replace your "grades" file with the contents of "g.out" by typing: rm grades mv g.out grades (I recommend that you print your grades file after every update!) Now here is the "input" program. (The : on the first line is important): : ############################################# # # input # # Usage: input filename # # Purpose: To add a column of scores to a grades file # # Output file: g.out # ############################################# nawk 'BEGIN {while (getline < "'"$1"'" > 0){ line=$0 printf("%s\t", $1) getline score=$0 print line "\t" score > "g.out"} exit } END {print "END OF FILE.\n" print "INPUT FILE: " "'"$1"'" "\t OUTPUT FILE: g.out" }' -