If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

 
Go Back  dBforums > Data Access, Manipulation & Batch Languages > Unix Shell Scripts > newbie to bourne shell question

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 01-18-04, 01:00
WhiteTree WhiteTree is offline
Registered User
 
Join Date: Jan 2004
Posts: 4
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
Reply With Quote
  #2 (permalink)  
Old 01-18-04, 07:18
chillies chillies is offline
Registered User
 
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 07:20.
Reply With Quote
  #3 (permalink)  
Old 01-18-04, 09:42
WhiteTree WhiteTree is offline
Registered User
 
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.
Reply With Quote
  #4 (permalink)  
Old 01-18-04, 12:57
chillies chillies is offline
Registered User
 
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.
Reply With Quote
  #5 (permalink)  
Old 01-18-04, 15:16
WhiteTree WhiteTree is offline
Registered User
 
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
Reply With Quote
  #6 (permalink)  
Old 01-18-04, 15:59
chillies chillies is offline
Registered User
 
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
Reply With Quote
  #7 (permalink)  
Old 01-18-04, 16:32
WhiteTree WhiteTree is offline
Registered User
 
Join Date: Jan 2004
Posts: 4
I also forgot to tell you that we are supposed to start the script with: #!/bin/sh.
Reply With Quote
  #8 (permalink)  
Old 01-18-04, 16:49
chillies chillies is offline
Registered User
 
Join Date: Jul 2003
Location: Edinburgh
Posts: 35
Quote:
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.
Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On