3

I'm very new at Bash Scripting so forgive my ignorance. I have a text file with last names that I am reading and processing line-by-line an average of three test scores. I need to output the lines sorted by last name. Here is what I have to compute the average, with a variable named OUTTOSORT that I was trying to pass to sort before being output.

#!/bin/bash
FILE=$1
OUTTOSORT=""

while read -r SID FIRST LAST S1 S2 S3
do
    SUM=$(expr $S1 + $S2 + $S3)
    AVG=$(expr $SUM / 3)
    OUTTOSORT = OUTTOSORT + "$AVG [$SID] $LAST, $FIRST \n"
done < "$FILE"

sort < $OUTTOSORT

When run:

engr2-6-52-dhcp:homework6 Matt$ ./Grades.sh 
./Grades.sh: line 10: : No such file or directory
./Grades.sh: line 12: $OUTTOSORT: ambiguous redirect

Any suggestions on how to sort these lines after computing the average would be very helpful. Thanks!

Edit:

Thanks very much for your answers! I now have a problem where it's not sorting by the field I specify however:

#!/bin/bash
FILE=$1
COUNT=0
while read -r SID FIRST LAST S1 S2 S3 
do
    SUM=$(expr $S1 + $S2 + $S3)
    AVG=$(expr $SUM / 3)
    printf '%d [%d] %s, %s (%d)\n' "$AVG" "$SID" "$LAST" "$FIRST" "$COUNT"
    COUNT=$((COUNT + 1))
done < "$FILE" | sort -k 3,3n -k 4,4n -k 2,2g

Output:

71 [299226663] Camp, Laney (5)
80 [434401929] Camp, Skyler (6)
81 [199144454] Camp, Tracey (4)
82 [123456789] Johnson, Lee (0)
82 [928441032] Forester, Jess (7)
91 [999999999] Smith, Jaime (1)
92 [888111818] Forney, JC (2)
93 [928441032] Forester, Chris (8)
99 [290010111] Lee, Terry (3)

As you can see, it is sorting by average score instead of by Last name, First name, SID. I added a counter to confirm it was sorting across the lines of the output. What error is causing the sort to not use the correct keys? Thanks!

Edit:

Solution to sort problem found: type flags for last name and first name should be d instead of n, making the sort command the while loop command pipes to sort -k 3,3d -k 4,4d -k 2,2g.

6

You can print the results to standard output, then pipe them to the sort command:

while read -r SID FIRST LAST S1 S2 S3
do
     SUM=$(expr $S1 + $S2 + $S3)
     AVG=$(expr $SUM / 3)
     printf '%d [%d] %s, %s\n' "$AVG" "$SID" "$LAST" "$FIRST"
done < "$FILE" | sort
  • 1
    This helped solve my problem with Hauke Laging thank you very much! – Matt Thompson Nov 9 '14 at 0:49
  • I'd guessed this would work, but didn't feel like trying to make a smaller dataset than the one I'm working with to try it on, so this answer saved me a lot of time writing a smaller test case by verifying that it would work as I anticipated. Thanks. – Wyatt8740 Jan 11 at 17:20
2

The bugs in your code / usage are (at least):

  1. The script calling: ./Grades.sh Due to FILE=$1 it must be ./Grades.sh /path/to/file

  2. OUTTOSORT = : There must not be a space on either side of the =

  3. OUTTOSORT = OUTTOSORT + (1) : Variables must be referenced with a $, i.e. OUTTOSORT=$OUTTOSORT

  4. OUTTOSORT = OUTTOSORT + (2) : There is no such string concatenation in bash.

  5. "...\n" : \n is not an escape sequence in normal strings. You need e.g. $'line1\n'

  6. sort < $OUTTOSORT : $OUTTOSORT must be a file here but it contains a string. You could do that with echo "$OUTTOSORT" | sort but easier is the combination of the while loop and sort in a pipeline as steeldriver suggested.

  • This helped solve my problem with steeldriver thank you very much! – Matt Thompson Nov 9 '14 at 0:49
1

Once you've fixed the errors enumerated by Hauke Laging, you can get sort to do what you want by telling it to do a numeric sort, and to use the 3rd field (the column containing the last name) as the sort key.

sort -n -k 3

See man sort for further details.

  • This helped for sorting, thanks very much! – Matt Thompson Nov 9 '14 at 0:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.