4

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.

3 Answers 3

7

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
2
  • 1
    This helped solve my problem with Hauke Laging thank you very much! Nov 9, 2014 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.
    – Wyatt Ward
    Jan 11, 2020 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.

1
  • This helped solve my problem with steeldriver thank you very much! Nov 9, 2014 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.

1
  • This helped for sorting, thanks very much! Nov 9, 2014 at 0:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .