jenna
jenna

Reputation: 27

divide floating point numbers from two different outputs

I am writing a bash script that has 1) number of lines in a file matching a pattern and 2) total lines in a file.

a) To get the number of lines in a file within a directory that had a specific pattern I used grep -c "pattern" f*

b) For overall line count in each file within the directory I used wc -l f*

I am trying to divide the output from 2 by 1. I have tried a for loop

for i in $a
do
printf "%f\n" $(($b/$a)
echo i
done

but that returns an error syntax error in expression (error token is "first file in directory")

I also have tried

bc "$b/$a" 

which does not work either

I am not sure if this is possible to do -- any advice appreciated. thanks!

Sample: grep -c *f generates a list like this

myfile1 500
myfile2 0
myfile3 14
myfile4 18

and wc -l *f generates a list like this:

myfile1 500
myfile2 500
myfile3 500
myfile4 238

I want my output to be the outcome of output for grep/wc divided so for example

myfile1 1
myfile2 0
myfile3 0.28
myfile4 0.07

Upvotes: 0

Views: 85

Answers (4)

RARE Kpop Manifesto
RARE Kpop Manifesto

Reputation: 2845

jot 93765431 | 

mawk -v __='[13579]6$' 'BEGIN { 

_^=__=_*=FS=__ }{ __+=_<NF } END { if (___=NR) {

   printf(" %\47*.f / %\47-*.f ( %.*f %% )\n",
          _+=++_*_*_++,__,_,___,_--,_*__/___*_) } }'
4,688,271 / 93,765,431  ( 4.99999941343 % )
  • filtering pattern = [13579]6$

Upvotes: 0

M. Nejat Aydin
M. Nejat Aydin

Reputation: 10133

bash doesn't have builtin floating-point arithmetic, but it can be simulated to some extent. For instance, in order to truncate the value of the fraction a/b to two decimal places (without rounding):

q=$((100*a/b)) # hoping multiplication won't overflow
echo ${q:0:-2}.${q: -2}

The number of decimal places can be made parametric:

n=4
q=$((10**n*a/b))
echo ${q:0:-n}.${q: -n}

Upvotes: 2

markp-fuso
markp-fuso

Reputation: 34643

bash only supports integer math so the following will print the (silently) truncated integer value:

$ a=3 b=5
$ printf "%f\n" $(($b/$a))
1.000000

bc is one solution and with a tweak of OP's current code:

$ bc <<< "scale=2;$b/$a"
1.66

# or

$ echo "scale=4;$b/$a" | bc
1.6666

If you happen to start with real/float numbers the printf approach will error (more specifically, the $(($b/$a)) will generate an error):

$ a=3.55 b=8.456
$ printf "%f\n" $(($b/$a))
-bash: 8.456/3.55: syntax error: invalid arithmetic operator (error token is ".456/3.55")

bc to the rescue:

$ bc <<< "scale=2;$b/$a"
2.38

# or

$ echo "scale=4;$b/$a" | bc
2.3819

NOTE: in OP's parent code there should be a test for $a=0 and if true then decide how to proceed (eg, set answer to 0; skip the calculation; print a warning message) otherwise the this code will generate a divide by zero error

Upvotes: 3

Ivan
Ivan

Reputation: 7287

This awk will do it all:

awk '/pattern/{a+=1}END{print a/NR}' f*

Upvotes: 1

Related Questions