How do I add a decimal value to a value in my bash script? [duplicate] - bash

This question already has answers here:
How to add an integer number and a float number in a bash shell script
(4 answers)
Closed 1 year ago.
I'm grabbing the tail of my output file and then want to add 0.000001 to that value.
So far I've tried it this way:
offset=0.000001
time=$(($(`tail -1 speed.txt1`) + $offset))

Bash itself does not have any floating point ability. You need to use another tool to get a float result in the shell.
Given:
cat file
1
2
3
You can use bc for floating point in the shell:
offset='0.000001'
printf "%s+%s\n" $(tail -1 file) "$offset" | bc
3.000001
Or awk:
awk -v offset="$offset" 'END{printf "%.7f\n", $1+offset}' file
3.000001
Since bc does not understand scientific notation (ie, 1.3E6) and you can still normalize that with printf in the shell:
x=1.33E6
printf "%f\n" "$x"
1330000.000000
And then pass to bc:
offset="1e-6"
x=1.33E6
printf "%f+%f\n" "$x" "$offset"
1330000.000000+0.000001
printf "%f+%f\n" "$x" "$offset" | bc
1330000.000001

Related

How to use multiple variable in for loop in sh? [duplicate]

This question already has answers here:
How do I pipe a file line by line into multiple read variables?
(3 answers)
Closed 18 days ago.
I want to use multiple variable in for loop at once in sh.
I have a query like this:
top -n 1 -b -c| awk -vOFS="\t" '{print $1,$2,$9}'
I know i use for loop in bash like this:
for i in {2..10}
do
echo "output: $i"
done
what i want to try is:
for x y z in $(top -n 1 -b -c| awk -vOFS="\t" {print $1,$2,$9}')
do
echo "output: $x $y $z"
done
Pipe to a while read loop:
top -n 1 -b -c| awk -vOFS="\t" '{print $1,$2,$9}' | while IFS=$'\t' read -r x y z
do
echo "output: $x $y $z"
done

Bash Script | Subtracting percentage from free disk space

Trying to subtract a percentage from a variable, preferable with floating point (11.3%) else 12%
freespace=100
subtract=$(($freespace-$freespace*.113))
Update 1:
Here is an explanation of what I am trying to accomplish:
I am reducing my actual free space by 11.3%. if the file that I am copying is bigger than the subtracted free space then the script will prompt the user to create more space. bc command returns a floating-point. For this to work the output of bc must be without decimal points. df -m command outputs in megabytes and without decimal points. I don't you can compare 18000 MB with 120000.00 MB (bc output) in bash.
source="/some/dir"
destination="/some/dir
freespace="$(df -m "${destination}" | tail -1 | awk '{print $4}')"
reduced_percentage=".113" # minus 11.3 percent of actual freespace
reduced_freespace=$(bc <<< "$freespace * (1-$reduced_percentage)")
source_size="$(du -sm "${files}" | tail -1 | awk '{print $1}')"
if [[ "${reduced_freespace}" -lt "${source_size}" ]] ; then
read -r -n 1 -p "you do not have enough free space, create free space to continue..."
elif [[ "${reduced_freespace}" -gt "${source_size}" ]] ; then
some commands
fi
done
you'll want to learn the bc command.
Try this, and then read more here.
freespace=100
pct=.113
subtract=$(bc <<< "$freespace * (1-$pct)")
You can use awk for float calculation
$awk -v freespace=100 'BEGIN {print freespace-(freespace) * 0.113}'
88.7
$

How to divide 2 integer numbers and get the output stored in float variable using ksh shell scripting? [duplicate]

This question already has answers here:
How do I use floating-point arithmetic in bash?
(23 answers)
Closed 3 years ago.
I have below values stored in the respective variables:
s=$(nice grep -i "sf WOW" *`date --date='1 hour ago' +%y%m%d%H`* | grep -i "TRAF:5" | wc -l)
f=$(nice grep -i "sf WOW" *`date --date='1 hour ago' +%y%m%d%H`* | grep -i "TRAF:7" | wc -l)
a=`expr $s + $f`
I need to store the division output in a float variable with an accuracy of 5 digits.
echo "scale=5; 355/113" | bc
3.14159

Converting string to floating point number without bc in bash shell script

I'm getting load average in a bash shell script like so
load=`echo $(cat /proc/loadavg | awk '{print $1}')`
I know piping to bc
load=`echo $(cat /proc/loadavg | awk '{print $1}') \> 3 | bc -l`
is used in almost all examples of how to cast $load as an int but this box does not have bc installed and I am not allowed to add it.
I tried
int=`perl -E "say $load - 0"`
I tried
int=${load%.*}
I tried
int=`printf -v int %.0f "$load"`
What I want to be able to do is
if [ "$int" -gt 3.5 ]; then
How do I get that to evaluate as intended?
You can use awk to produce a success/failure depending on the condition:
# exit 0 (success) when load average greater than 3.5, so take the branch
if awk '{ exit !($1 > 3.5) }' /proc/loadavg; then
# load average was greater than 3.5
fi
Unfortunately, since "success" is 0 in the shell, you have to invert the logic of the condition to make awk exit with the required status. Obviously, you can do this in a number of ways, such as changing > to <=.
You don't need any external tools (like awk) to read this stuff. Load average from /proc/loadavg is always formatted with two decimal places, so you can do this:
read load _ < /proc/loadavg
if [ ${load/./} -gt 350 ]; then
# do something
fi

How to calculate extra large numbers with bc in bash

I have a file with 1800 lines that look like this
600.76
600.66
700.44
566.66
Ect..
I made a bash script to calculate the mean.
Now I first made a variable to count the total column lines like:
Lines="$(awk 'END{print NR}' file.txt)"
Then another variable for the sum of that column like this:
Sum="$(awk '{s+1=$1}END {print s}' file.txt)"
Lastly I'm finding the mean like this:
Echo "scale=2 ; $Sum / $Lines" | bc
With debugging enabled It returns:
+echo 'scale=2 ; 1.72161e+06 / 1800'
(Standard_1): syntax error
I realize now bc doesn't do scientific notation but how do I get around this.
I'm OK with short handing the decimal by restricting it to 2 or 3 places.
Unnecessary to use awk. Simple oneliner can do the job.
echo "scale=2; ("$(paste -sd+ file.txt)")"/$(wc -l <file.txt)|bc
Use bc -l for both summation and final division:
sum=0
count=0
while read number; do
number=$(printf "%f\n" $number) # get rid of scientific notation
sum=$(echo "$sum" '+' "$number" | bc -l)
count=$((count + 1))
done < input
avg=$(echo $sum / $count | bc -l)
echo $avg

Resources