Basic Mathematics from shell command line

It is possible to do a lot of calculations from command shell itself without using any spreadsheet applications or scripting languages like perl or python. What we require is simple un*x applications like, bc, xargs, awk etc.

To sum a list of numbers

  • There are many different ways to do that, but the best way I like is using xargs, tr and bc
  • $ command | xargs | tr ' ' '+' | bc -l
    where command could be either ‘cat filename’ or the output of any other command. The beauty of this command is that, it works regardless of the number of columns or rows in the file. Even, blank lines would not create any problem. The following file has got extra white spaces and blank lines and xargs arranges them in a single line with one space between them beautifully.

    $cat somefile.txt
         1
     2 3
    
       4  5 6
    
    


    bc is arbitrary precision, so that, it could handle any big number.

  • If we want to sum a column of numbers, it is possible to use awk also, for example to find the sum of the size of all files in a directory, do the following
  • $ ls -l | awk '{s+=$5} END {print s}'

    This command is also not susceptible to blank lines.

  • If there are no blank lines, even paste along with bc could be used
  • $ command | paste -sd+ | bc -l

    To multiply a list of numbers

  • For example, to find factorial of a number, say 10
  • $ for ((k=1;k<=10;k++)) do echo $k; done | xargs | tr ' ' '*' | bc -l

    or

    $ for ((k=1;k<=10;k++)) do echo $k; done | paste -sd* | bc -l

    To sum a list of hexadecimal numbers and to display their sum in hexadecimal

    The following command line runs a ‘for’ loop to generate numbers from 0x00 to 0xff (255), compute the sum and prints the output in hexadecimal itself.

    $ for ((k=0;k<256;k++)) do printf "0x%x\n" $k; done \
    | sed -e 's/^0x//g' | tr '[a-f]' '[A-F]' \
    | xargs echo 'obase=16;ibase=16;0' | tr ' ' '+' | bc -l

    Actually bc does not accept the hexadecimal prefix ‘0x’, that is the reason of using sed to remove the 0x prefix.  Also bc expects uppercase of 0xa to 0xf, so ‘tr’ is used translate them.  The ‘0’ inside the echo statement is used so that there is a number before the first ‘+’, if we want to remove the hack of using a ‘0’, the above command could be modified to the following.

    $ for ((k=0;k<256;k++)) do printf "0x%x\n" $k; done \
    | sed -e 's/^0x//g' | tr '[a-f]' '[A-F]' \
    | xargs | tr ' ' '+' | xargs echo 'obase=16;ibase=16;' | bc -l

    Or with a sub shell and a single xargs

    $ for ((k=0;k<256;k++)) do printf "0x%x\n" $k; done \
    | sed -e 's/^0x//g' | tr '[a-f]' '[A-F]' \
    | (echo -ne 'obase=16;ibase=16;' && xargs) | tr ' ' '+' | bc -l

    The above commands could be used for binary or octal also by replacing the ibase and obase to 2 or 8 respectively. Note that, it is better to write obase first. If ibase is written first, then obase has to be specified in terms of ibase
    That means
    obase=16;ibase=16
    and ibase=16;obase=10 are the same

    Advertisement

    Published by Anand Sivaram (आनन्दः )

    twitter.com/anand_sivaram https://www.linkedin.com/in/anandsivaram/

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out /  Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out /  Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out /  Change )

    Connecting to %s

    %d bloggers like this: