Results 1 to 8 of 8
  1. #1
    Join Date
    Jan 2004
    Posts
    4

    Unanswered: newbie to bourne shell question

    Im stuck on a file reading question. Ive got a file that looks like this:
    1 5 4 2 3
    6 7 8 9 9
    1 4 5 6 3
    8 7 4 1 5
    2 5 8 3 9
    3 6 5 3 4
    I want to calculate the average for rows and columns.
    Ive got a while loop that looks like this :

    while read line
    do
    number=`echo "$line" | cut -c1` #or i could use -f1 and it will still work
    sum=`expr $number + $sum`
    done < $1
    problem here is that this only gives me the average of the first column ( 1+6+1+8+2+3)/6 where I have to manually divide it by six ( my second problem).

    1)How can I make it compute all the averages of the other columns?
    2)I have no idea how to do the same with the rows. Also is there some way to automatically detect the number of rows and the number of columns and set those values to variables so I can calculate the averages.

    Thanks

  2. #2
    Join Date
    Jul 2003
    Location
    Edinburgh
    Posts
    35

    Re: newbie to bourne shell question

    the awk utility has all the functionality you require and should be available in your installation. You are making a rod for your own back if you want to write it in the shell itself. The awk language syntax is similar to C and splits the input file into columns automatically.

    Place the following text in a script, and you can determine the averages "./script.awk file.dat"

    #!/path/to/awk -f
    {
    THISROW=0;
    NROWS+=1;
    NCOLS=NF;
    for (i=1; i<=NF; ++i)
    {
    COL[i]+=$i;
    THISROW+=$i;
    }
    printf "%s%s%5.2f\n", $0, " row average: ", THISROW/NF;
    }

    END {
    print "-----------------";
    printf "%s", "Column averages: "
    for (i=1; i<=NCOLS; ++i)
    {
    printf "%5.2f ", COL[i]/NROWS;
    }
    printf "\n";
    }
    Last edited by chillies; 01-18-04 at 08:20.

  3. #3
    Join Date
    Jan 2004
    Posts
    4
    You see. Im not supposed to use the awk utitility. Ive heard of it and it sounded real easy to use. Thank you very much for the reply though. Do you have any other ideas other than using the awk util. Thanks for your help.

  4. #4
    Join Date
    Jul 2003
    Location
    Edinburgh
    Posts
    35

    more questions

    Which shell are you using? bash allows variable arrays so you can use a similar method to the previous example. And why not use awk? Are you doing a programming assignment?

    Which other utilities can be used? Can one use sed? I see you used expr and cut in the original post.

  5. #5
    Join Date
    Jan 2004
    Posts
    4
    Im doing part of a programming assignment and Im supposed to use bash. The utilities im supposed to use are read, expr, cut, head, tail, wc, and sort. Thanks for the reply

  6. #6
    Join Date
    Jul 2003
    Location
    Edinburgh
    Posts
    35
    Here you go ... it does the column averages of stdin and there's enough in there to allow you to sort out the row averages.

    I'm using GNU bash, version 2.05b.0(1)-release (i686-pc-cygwin) which seems to have wierd behaviour in read when the input file doesn't end with a newline. That's why there's the line with the -z test.

    I'm sad that you can't use dc, as it's quite nice to use a stack-based language. This script with expr uses integer arithmetic and rounds down.

    One reason I'm answering posts in this forum is that I've volunteered to give a bash demo/tutorial for the local linux user group, and I'm trying to get some revision. I'd appreciate if you could post other questions from the course so I can gauge the topics I'd have to cover. And say which level the course is, too. Thanks.

    #!/path/to/bash

    declare -a COLSUM

    dbforums () {
    let LINES=$LINES+1
    [ $LINES == 1 ] && NCOLS=${#COL[*]}
    for (( i=0; i<$NCOLS; ++i )); do
    let COLSUM[$i]+=COL[$i]
    done
    }

    LINES=0
    while read -a COL
    do
    dbforums
    done
    [ -z "${COL[0]}" ] || dbforums

    for (( i=0; i<NCOLS; ++i ))
    do
    # dc -e "2 k ${COLSUM[$i]} $LINES / n [ ] n"
    echo -n "$(expr ${COLSUM[$i]} / $LINES) "
    done
    echo

  7. #7
    Join Date
    Jan 2004
    Posts
    4
    I also forgot to tell you that we are supposed to start the script with: #!/bin/sh.

  8. #8
    Join Date
    Jul 2003
    Location
    Edinburgh
    Posts
    35
    Originally posted by WhiteTree
    I also forgot to tell you that we are supposed to start the script with: #!/bin/sh.
    Hmmm ... Usually the # character indicates the remainder of a line is a comment, except when it's the first character on the first line and is followed by an exclamation mark. In that case, the kernel uses the remainder of the line as the interpreter (and any flags) to run. #!/path/to/bash is a shorthand I've used that you should replace with the path to your bash interpreter.

    If you're on linux /bin/sh is usually linked to to bash, but if you actually have to use the Bourne shell (/bin/sh) then you won't have arrays and you'll have to find another solution.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •