5

Say I have these two input files:

> file1
2
3
4

> file2
10
100
1000

And I would like to compute: file1/file2 for each line, resulting in file3:

> file 3
0.2
0.03
0.004

Divisions in bash can be achieved by: $((file1_line/file2_line))

dovah
  • 1,717

2 Answers2

11

A paste and bc combination is a good choice for simple arithmetic:

paste -d/ file1 file2 | bc -l

Output:

.2000000000
.0300000000
.0040000000

A more advanced example

With some trickery you can get a bit more complicated. Say file3 contains:

6
7
8

You can do (file1 + file3) / file2 like this:

paste -d'(+)/' /dev/null file1 file3 /dev/null file2

Output:

(2+6)/10
(3+7)/100
(4+8)/1000

This works because paste cycles through its delimiter list for each line.

React to divide-by-zero

Illigal operations sent to bc result in a warning being sent to standard error. You could redirect these to a different file and decide program flow based on its content, e.g.:

paste -d/ file1 file2 | bc -l > resultfile 2> errorfile
if grep -q 'Divide by zero' errorfile; then
  echo "Error in calculation"
else
  echo "All is well"
fi

Or if there was any error:

paste -d/ file1 file2 | bc -l > resultfile 2> errorfile
if ! file errorfile | grep -q empty; then
  echo "Error in calculation"
else
  echo "All is well"
fi
Thor
  • 17,182
  • Thanks @Thor. Do you think it is possible to integrate an exit/skip status for any division by zero? As in: http://unix.stackexchange.com/questions/28016/ignore-or-catch-division-by-zero – dovah Aug 22 '16 at 09:19
  • @dovah: bc gives you a divide-by-zero warning, so it should be straightforward to integrate. It just depends on what you mean by that – Thor Aug 22 '16 at 09:23
  • 1
    @dovah: Added a divide-by-zero example – Thor Aug 22 '16 at 11:49
7

start with

 paste file1 file2 | awk '{printf "%f\n",$1/$2 } '

where

  • paste will "merge" file
  • awk will compute division, one at a time.

if you don't like too many trailling 0's, just add

... | sed -e s/0*\$//

to exit in case of 0

paste file1 file2 | awk '!$2 {exit ; }  {printf "%f\n",$1/$2 } '
Archemar
  • 31,554