0

How do you make a bash script to add and then count how many numbers the user inputted? I cant see how to do variables since the user can potentially enter infinite inputs. If the user enters nothing its supposed to give an error message. This is the code I have so far, its probably wrong so go easy on me I'm still a beginner.

#!/bin/bash
if [ read = null ]
  echo "Invalid input."
else
  echo "please input numbers to add"
  #add numbers inputted
  read num1 num2 num3 num4 num5 num6 num7 
  #i put 7 variables but it needs to add however many numbers the user puts
  TOTAL=$((num1+num2+num3+num4+num5+num6+num7))
  #count how many numbers are inputted
  read num1 num2 num3 num4 num5 num6 num7
  wordCount=$((num1+num2+num3+num4+num5+num6+num7 | wc -c))
  echo "Your total is $TOTAL and the number of inputs you entered is $wordCount"\
fi

Cyrus
  • 12,309
  • 1
    Always paste your script into https://shellcheck.net, a syntax checker, or install shellcheck locally. Make using shellcheck part of your development process. – waltinator Nov 29 '21 at 03:48

2 Answers2

3
  1. That if [ read = null ] line is nonsense. It doesn't make any sense at all.

  2. You're using bash, so you can read the numbers into an array, rather than a fixed number of variables.

Try something like this:

$ cat add.sh
#!/bin/bash

while true; do printf "Please input numbers to add: " read -r -a numbers

exit if input is empty

[ "${#numbers[@]}" == 0 ] && break

check if input consists only of numbers

(integers or decimals allowed)

for n in "${numbers[@]}"; do if ! [[ "$n" =~ ^[0-9]+(.[0-9]+)?$ ]] ; then echo "Invalid input: $n" continue 2 fi done

expression="$(printf "%s+" "${numbers[@]}" | sed -e 's/+$//')" echo "$expression" | bc done

This loops forever (while true), asks for input and reads the input into array numbers.

If the number of elements in numbers is zero, it exits the while loop with break. BTW, "${#numbers[@]}" returns the number of elements in the array - i.e. the "word count" you want. You can just print this with echo or printf if you want. I'm not going to do all of your homework for you, so I'll leave that for you to do.

If any of the input elements isn't a number, it prints "Invalid input" and returns to the beginning of the while loop (with continue 2 - the 2 argument is necessary because at this point the script is inside a while loop and a for loop. Without the 2, it would only exit the for loop, i.e. it would print "Invalid input" and then try to perform the calculation)

Otherwise it constructs a string (in a variable called expression) using printf. sed is used to strip the trailing + from the end of the string.

Then it pipes the expression into bc, which is a calculator tool. Unlike bash's built-in integer-only arithmetic, bc can handle floating point numbers. bc may not be installed by default on your system, but if you're running Linux, it should be available as a package (e.g. on Debian, it's in the bc package). It's part of the POSIX spec, so should be available for other unix variants too, see https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html

$ ./add.sh 
Please input numbers to add: 1 2 3
6
Please input numbers to add: 1 2 3 xyz
Invalid input: xyz
Please input numbers to add: 4 5 6 7 8 9
39
Please input numbers to add: 

In this example run, the first input line is turned into the expression 1+2+3 and then piped into bc to perform the calculation. The third input line is turned into 4+5+6+7+8+9 and piped into bc.

cas
  • 78,579
  • 3
    BTW, I'm not giving you an answer for you to copy and paste into your homework without understanding it. I'm giving you an example for you to take the time to read and understand and experiment with it, then rewrite it in whatever way makes sense to you. I very strongly recommend that you do so. If you haven't shown any aptitude for writing bash scripts before, your teacher is very unlikely to believe that you wrote anything like this. They will almost certainly ask you to explain how it works and probably fail you if you can't demonstrate that you understand it. – cas Nov 29 '21 at 04:32
1

Shells, especially bash are not very good at doing arithmetic by themselves. Not only that, but letting them do arithmetics on user provided input generally constitutes an arbitrary command execution vulnerability.

What they're good at however is running commands as that's what they're for.

#! /bin/sh -
awk 'BEGIN {printf "Enter numbers, space separated: "}
     {
       sum = 0
       for (i = 1; i <= NF; i++) sum += $i
       print "Sum of those "NF" numbers: "sum
       exit
     }'

There, the shell (here using sh as there's no need for bash) calls awk which processes one¹ line of input and adds the value of each field. awk supports integers and floating point numbers and doesn't have bash's issue whereby numbers with leading 0s are treated as octal and doesn't have the shell arithmetic ACE vulnerability

When trying to decode a string as a number, it does what it can, stopping when it can't recognise it (1e4foo would be 1e4 aka 10000, whatever would be 0 for instance).


¹ though could read more than one if the input is not coming from a terminal.

  • It would be interesting to get your comment on not using an 'awk shebang'. – sudodus Nov 30 '21 at 08:53
  • 1
    @sudodus, with an awk she-bang, you'd need to add extra code to handle the list of arguments to the script (to ignore them). Also, only gawk can be used reliably in shebangs (with its -E option) – Stéphane Chazelas Nov 30 '21 at 13:37