Reputation: 41
I'm a bit confused by the done < $1
notation.
I'm trying to write a program "sumnums" that reads in a file called "nums" that has a couple rows of numbers. Then it should print out the rows of the numbers followed by a sum of all the numbers.
Currently I have:
#!/bin/bash
sum=0;
while read myline
do
echo "Before for; Current line: \"$myline\""
done
for i in $myline; do
sum=$(expr $sum + $i)
done < $1
echo "Total sum is: $sum"
and it outputs the list of the numbers from nums correctly then says
./sumnums: line 10: $1: ambiguous redirect
, then outputs Total sum is: 0
.
So somehow it isn't adding. How do I rearrange these lines to fix the program and get rid of the "ambiguous redirect"?
Upvotes: 3
Views: 12308
Reputation: 295716
Assuming your filename is in $1
(that is, that your script was called with ./yourscript nums
):
#!/bin/bash
[[ $1 ]] || set -- nums ## use $1 if already set; otherwise, override with "nums"
sum=0
while read -r i; do ## read from stdin (which is redirected by < for this loop)
sum=$(( sum + i )) ## ...treat what we read as a number, and add it to our sum
done <"$1" ## with stdin reading from $1 for this loop
echo "Total sum is: $sum"
If $1
doesn't contain your filename, then use something that does contain your filename in its place, or just hardcode the actual filename itself.
Notes:
<"$1"
is applied to a while read
loop. This is essential, because read
is (in this context) the command that actually consumes content from the file. It can make sense to redirect stdin to a for
loop, but only if something inside that loop is reading from stdin.$(( ))
is modern POSIX sh arithmetic syntax. expr
is legacy syntax; don't use it.Upvotes: 4
Reputation: 67547
awk
to the rescue!
awk '{for(i=1;i<=NF;i++) sum+=$i} END{print "Total sum is: " sum}' file
bash
is not the right tool for this task.
Upvotes: 0