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
$ 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.
$ ls -l | awk '{s+=$5} END {print s}'
This command is also not susceptible to blank lines.
$ command | paste -sd+ | bc -l
To multiply a list of numbers
$ 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