Home > Net >  Sum of three absolute values in Bash?
Sum of three absolute values in Bash?

Time:12-13

I'm trying to make a Bash script that would compute the sum of three values of integers given in a single line separated by space

# you can use `read` to get standard input
read x y z
echo "$((${x#-}   ${y#-}   ${z#-}))"

The code I have written here works, however is not the best version, any idea on optimizing it so that it would run more efficiently?

CodePudding user response:

you should be using the parenthesis method to do the arithmetic of the numbers for example if you are adding two numbers x and y and if you want to store it in the variable z then simply do it by z=$((x y)) and printing z on screen as echo $z

so ((...)) evaluates the expression between the parenthesis. so basically the sum of three numbers could be done as follows:

z=$((a b c))
echo $z

but if you want to do absolute addition of the numbers , you can use

the indexing method to remove the negative sign

for example :

#to check if number is negative and changing to positive if it is
if [[ 0 -gt $x ]]
then    
    x=${x:1}
fi

and now you can perform the additon as usual using parenthesis

CodePudding user response:

Read values and turn them absolute at the same time by including - and as field delimiters.

# Reads (space, plus and minus) delimited absolute numbers.
# Do not forget an extra dummy variable _
# to avoid collecting delimiters inside z.
IFS=' - ' read -r x y z _

# Prints the sum.
printf '%d   %d   %d = %d\n' "$x" "$y" "$z" $((x   y   z))

Collecting values inside an array would allow computing the sum of arbitrary number of values like this:

#!/usr/bin/env bash

# Reads numbers in an array, treating space, minus and plus
# as delimiters so array contains only absolute numbers
IFS=' - ' read -r -a numbers

# Saves the Internal Field Delimiter.
_OIFS=$IFS

# Sets the delimiter to be a plus.
IFS= 

# The numbers array is expanded to a string
# with elements delimited
# by the value of IFS (a plus sign).
# Literally expanding the array into a sum expression of its elements.
printf '%d\n' $((${numbers[*]}))

# Restores the original delimiter.
IFS=$_OIFS

CodePudding user response:

This should do

#!/bin/bash

echo "Enter 3 numbers (space-seperated): ";
IFS=' ' read a b c;

(( TOTAL = a   b   c ));  

# or alternatively,
# TOTAL="$(( a   b   c ))";                                                                                                                                                                 

echo "The result is ${TOTAL}";

The (( ... )) construct uses arithmetic evaluation, which means every variable is treated as a number/integer with empty/missing values being 0.

It also lets you use the variables without the usual $a or ${a} notation, which makes the whole thing a lot cleaner (and more readable).


The IFS variable for the read command, should you not recognize it, is the Internal Field Separator; It basically just makes it explicit that you want read to split the input on space characters. You could theoretically set it to ',' and have the user enter 5,6,7 and so on. The default is inherited from your shell which is generally IFS=$' \n\t'; (spaces, newlines or tabs). It tends to be a good idea to make explicitly setting it, a habit.

  • Related