Arithmetic operations within column with awk or sed

arithmetictext processing

I have a file whose columns contain simple arithmetic equations that I would like to merge to the arithmetic result.

Input sample (tab-separated columns):

+104-1+12   6   +3

I would like to compute the arithmetic sum within each column. If one column contains no arithmetic sign, I treat it as it contained a + before the item. Although it would be easy through sed to add a + sign if a column starts with no sign (sed -E 's/(\t)([0-9]*)/\1\t+\2/g' would work, assuming that a row never begins with a digit, as in the example)

The output I would expect is the following:

115 6   3

How can I achieve this in unix? awk/sed solutions are preferred.

Best Answer

You could use perl:

perl -pe 's/[\d+-]+/eval$&/ge' your-file

Or even:

perl -pe 's/[\d+-]+/$&/gee' your-file (thanks Rakesh)

Same with zsh:

set -o extendedglob # for the ## operator (same as ERE +)
while IFS= read -r line; do 
  printf '%s\n' ${line//(#m)[0-9+-]##/$((MATCH))}
done < your-file

Or:

zmodload zsh/mapfile
set -o extendedglob
printf %s ${mapfile[your-file]//(#m)[0-9+-]##/$((MATCH))}

In all four, we're looking for sequences of digits, - and + characters and passing them to the interpreter's arithmetic processor (eval in perl (or the ee flag that causes the expansion of the replacement to be evaluated as perl code), $((...)) in zsh).

We're not validating the expressions before passing to the interpreter, so it may cause failures (for instance on sequences like -+- or 3++) but at least, because we're only considering digits and -/+ characters, it shouldn't do much more harm than reporting an error message and aborting the command.

Related Question