13

I'm trying to write a bash script and I needed to do some floating point math. Basically I want to do something like this:

NUM=$(echo "scale=25;$1/10" | bc)
if [ $? -ne 0 ]
then
echo bad
fi

The problem I'm running into is $? tends to hold the output from the echo program and not the bc call. Is there a way I save the output from the bc program into a variable?

EDIT:

Thanks for the quick replies. Here's another way of looking at the problem. Say I modified the script a little bit so it looks like this:

#!/bin/bash
NUM=$(echo "scale=25;$1/10" | bc)
if [ $? -ne 0 ]
then
echo bad
exit
fi
echo "$NUM"

When the user inputs a normal floating point value, it works fine:

bash script.sh 1.0

output:

.1000000000000000000000000

However, when the user enters an incorrect value, the script can't recover:

bash script.sh 1.0a

output:

(standard_in) 1: parse error

What I'm trying to do is get it to exit gracefully.

3 Answers 3

12

I don't see anything wrong. $NUM is supposed to hold your bc command results

see:

NUM=$(echo "scale=25;$1/10" | bc)
echo "\$? is $?"
echo "NUM is $NUM"

output

$ ./shell.sh 10
$? is 0
NUM is 1.0000000000000000000000000

another way is to use awk

NUM=$(awk -vinput="$1" 'BEGIN{printf "%.25f", input/10 }')
echo "\$? is $?"
echo "NUM is $NUM"

The other way, is to do the check of "$1" before you pass to bc. eg

shopt -s extglob
input="$1"
case "$input" in
 +([0-9.]))
     IFS="."; set -- $input
     if [ $# -ne 2 ];then
        echo "bad decimal"
     else
        NUM=$(echo "scale=25;$1/10" | bc  )
        echo "$NUM"
     fi
esac

you don't have to check for $? from bc anymore

Sign up to request clarification or add additional context in comments.

4 Comments

Remember that the successful echo of 'NUM is $NUM' will have overwritten the value in $? from the '$(echo ... | bc)' command.
I clarified my post above. Thanks for the tip on awk. If I can't get bc to work, I'll have to check it out.
another way, is to sanitize your input $1 to be a decimal or number before passing to bc. see my edit.
That's a cleaver check, but is there any way to make sure there's only one '.' character present? Thanks.
2

For GNU bc, an error similar to "(standard_in) 1: syntax error" will be output on stderr. You can capture this in your variable and check for it.

#!/bin/bash
NUM=$(echo "scale=25;$1/10" | bc 2>&1)
if [[ $NUM =~ error || $? -ne 0 ]]
then
    echo bad
    exit
fi
echo "$NUM"

Comments

1

Are you after the result of calculation from bc (which you store in NUM) or the status return from the system call?

As I said you have the result of calculation in $NUM:

#bctest.sh
NUM=$(echo "scale=25;$1/10" | bc)
if [ $? -ne 0 ]
then
echo bad
fi

echo "result: ", $NUM

Test:

bash ./bctest.sh 15
result: , 1.5000000000000000000000000

1 Comment

I was trying to get the status return from the system call. Sorry, I should have been more explicit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.