1

I have an assignment for school which is to create a script that can calculate a math equation any length using order of operations. I had some trouble with this and ended up finding out about here-strings. The biggest problem with the script seems to be error-checking. I tried to check the output of bc using $?, however it is 0 whether it is success or fail. In response to that I am now attempting to store the output of the here-string into a variable, and then I will use regex to check if output begins with a number. Here is the piece of code I wish to store in a variable, followed by the rest of my script.

#!/bin/bash
set -f
#the here-string bc command I wish to store output into variable
cat << EOF | bc
scale=2
$*
EOF


read -p "Make another calculation?" response
while [ $response = "y" ];do
    read -p "Enter NUMBER OPERATOR NUMBER" calc1
cat << EOF | bc
scale=2
$calc1
EOF
read -p "Make another calculation?" response
done
~
OrcMan
  • 69
  • 10
  • 1
    Useless use of cat. Save a pipe today and use `bc << EOF`. – Jens Mar 13 '17 at 22:38
  • Thanks I will try it, but do you know how I can store the output in a variable? – OrcMan Mar 13 '17 at 22:41
  • 2
    BTW, http://shellcheck.net/ is your friend. `[ $response = "y" ]` quotes exactly the *wrong* thing -- the `y` doesn't need to be quoted because it's a constant, the `$response` *does* need to be quoted because it's an expansion. – Charles Duffy Mar 13 '17 at 22:52
  • Just a comment. The `command << EOF ... EOF` construction is **here doc**. The **here string** is bash-ism and could be written as `command <<< "content of the stdin for the command"` (note the `<<<` instead of `<<`). – clt60 Mar 13 '17 at 23:11

1 Answers1

4

This should do the trick:

#!/bin/sh

while read -p "Make another calculation? " response; [ "$response" = y ]; do
    read -p "Enter NUMBER OPERATOR NUMBER: " calc1
    result=$(bc << EOF 2>&1
scale=2
$calc1
EOF
)
    case $result in
    ([0-9]*)
         printf '%s\n' "$calc1 = $result";;
    (*)
         printf '%s\n' "Error, exiting"; break;;
    esac
done

Sample run:

$ ./x.sh
Make another calculation? y
Enter NUMBER OPERATOR NUMBER: 5+5
5+5 = 10
Make another calculation? y
Enter NUMBER OPERATOR NUMBER: 1/0
Error, exiting

Note that you might do this without a here-document like this:

result=$(echo "scale=2; $calc1" | bc 2>&1)
Jens
  • 69,818
  • 15
  • 125
  • 179
  • 1
    BTW, is `read -p` valid with `/bin/sh`? I was under the impression it was a bashism, and don't see it in http://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html. Though, a bashism that dash implements is admittedly not *much* of a bashism. :) – Charles Duffy Mar 13 '17 at 22:56
  • 1
    @CharlesDuffy Yes, it's non-POSIX, but not a bashism, more like a manyshellism :-). FreeBSD ash, zsh and probably others accept it. – Jens Mar 13 '17 at 22:59
  • 1
    Well, sure -- most "bashisms" are actually things that started with ksh, and picked up by other spiritual successors as well. (Given how much POSIX sh itself was influenced by early ksh...) – Charles Duffy Mar 13 '17 at 23:01
  • Thanks Jens, your solution to do the calculation without a here-document worked perfectly. I am able to error-check and display the usage message :) – OrcMan Mar 13 '17 at 23:01
  • 1
    @KieranO'Connor Glad to help. Welcome to Stackoverflow. – Jens Mar 13 '17 at 23:03