[KSH] Creating automatic variable from read input

Hello there, I am posting to seek help with a KSH script,

I am making a simple calculation program where the user can enter as many numbers as they like, I am getting their input using the read command, however I am not sure how to repeat doing this and storing the input in to new variables until the user wants the program to calculate.

Here is what I have so far

#!/bin/ksh

echo "Please input two numbers"
echo
echo "Please input value 1: "
read x1
echo
echo "Please input value 2: "
read x2

echo "The answer is: "
echo
echo "($x1 + $x2 | bc))"

I am thinking maybe using an Array is the best way to go about this, but I am really stumped on how to do this :wall:

Don't take it as a solution (it's not), take it as a hint:

#!/bin/ksh

unset array
typeset -a array
while true; do
 echo "Input a number (just press ENTER to stop): "
 read input
 [[ "$input" = "" ]] && break
 array+=( "$input" )
done

echo ${array[@]}

unset sum
for ((i=0;i<${#array[@]};i++)); do
 sum=$(( $sum + ${array[$i]} ))
done

echo $sum

--
Bye

I guess I'm really missing something here. Why do you believe that an array is needed here? Why not just keep a running total as you gather numbers? This is written assuming ksh, but should work for any POSIX-conforming shell (not csh and not tcsh):

#!/bin/ksh
GetNumMsg='Enter a number (ctrl-d when done): '
printf "$GetNumMsg"
sum=0
while read x
do      sum=$((sum + x))
        printf "$GetNumMsg"
done
printf "\nSum of numbers entered is: %d\n" $sum

I guessed he wanted flexibility.

First he collects data, then he can use (and reuse) them to calculate as many things as he needs (even easily changing his code).
--
Bye

Hi Lem,
You suggested an array because pandapowerbox said in the 1st message in this thread:

I am thinking maybe using an Array is the best way to go about this, but I am really stumped on how to do this

My question and suggestion were directed to pandapowerbox, not to you. Your script was an excellent example of how to use an array to solve a problem like this; if an array is needed. I'm sorry for the confusion.

Pandapowerbox,
I see a lot of newbie programmers who pay too much attention to the semantics of a possible solution without stepping back to look at the bigger picture. If you start out thinking that you need to add a list of variables and print the sum, then you think about accumulating an array and adding them at the end. But, if your goal is just to get the sum of a list of values, you make the problem much more complex by assuming you need to save the input values as separate variables or as separate members of an array instead of just keeping a running sum as you read each individual value.

I also note that the last line of your starting script:

echo "($x1 + $x2 | bc))"

almost certainly doesn't do what you wanted it to do.

By passing the quoted string to echo, it expands $x1 and $x2, but doesn't invoke bc. And, if you had left off the double quotes, you also have mismatched parentheses. And, if you had used: echo ($x1 + $x2 | bc) or echo (($x1 + $x2 | bc)) you would have had ksh syntax errors. You could have used echo $($x1 + $x2 | bc) and gotten the result you were probably expecting, but if you're learning ksh, you should look at arithmetic expansion that does all of the work in the shell without needing to invoke another utility (bc in this case). Using arithmetic expansion this would simply be: echo $((x1 + x2)) .

You have probably already noticed that the suggestions that Lem and I provided both use ksh's arithmetic expansions sum=$(( $sum + ${array[$i]} )) and sum=$((sum + x)) , respectively, rather than invoking awk, bc, dc, expr, perl, or some other utility to perform these simple calculations.

Hopefully, the comments Lem and I have made will help you see that there are almost always several ways to do something in shell scripts and help you think about a few of the possibilities as you tackle new problems like this.

Hey guys

Thanks for the detailed replies, they have really helped me a great deal!!

@Don: I decided to maybe use an Array as I wasn't aware of any other way of doing what I wanted to do using KSH ... I have only been using it for a week but I guess I have been proven wrong that I can do what I need without an Array.

Ksh93, bash, ... give also little nicer syntax version for the arithmetic expansion .
You can put everything inside (( )) and use variables without dollar sign $.
This is not Posix compatible, but look easier to read. Works only in the arithmetic expansion using (( )).

In this example input values has saved to the array and to the string (inputstr).

inputstr=""
while true
do
 echo -e -n "Input a number (just press ENTER to stop): "
 read input
 [ "$input" = "" ] && break
 array+=( "$input" )              # new element to the array
 inputstr="$inputstr $input"    # join string
done

echo ${array[@]}

sum=0
# take all values from the list, in this case all values from array
for val in ${array[@]}
do
    (( sum+=val ))   # works in ksh93, bash, ...
    # sum=$(( $sum + $val ))  # posix compatible, you can use also let command
done

echo $sum

# or using inputstr
sum=0
for val in $inputstr
do
    (( sum+=val ))   
done

echo $sum

That's the usual reason I hear for using arrays in shell, honestly. But storing all your input in variables before you use it is, in general, a terrible idea. Hopefully the discussion in this thread has given you other ideas.