# Arithmetic calculation row-wise for non-fixed column number

I have an input file with non-fixed column number on which I would like to do some arithmetic calculations on:

``````input.txt
ID1    4651455    234     4651765    392     4652423      470
ID2    16181020   176    16184958    869     16185889     347    16187777     231
``````

The input file has tab-separated fields has always a unique `ID` in column `\$1` (not duplicated). Not all rows have the same number of columns.

What I would like to achieve is a tab-separated file as follows:

`````` output1.txt
ID1     76    266
ID2     3762   62   1541
``````

Basically it would print the `\$1` of the original file, then it would start from the second even column of the file (`\$4`) and subtract to its value the previous two columns (`\$4`-`\$3`-`\$2`) then do the same with all the even columns of the input file (e.g., `\$6`-`\$5`-`\$4`; `\$8`-`\$7`-`\$6`; ...). In my knowledge, this can be done with `awk print`, but I only know how to deal with it when my file has a fixed number of columns in every row.

An even more ideal output for my needs would be the following:

``````output2.txt
ID1    234    76    392    266   470
ID2    176   3762   869    62    347   1541  231
``````

Basically it would print the `\$1` of the original file, then interleave printing the odd columns from the input file to the columns as in `output1.txt`.

``````\$ awk -v OFS='\t' -f script.awk file
ID1     76      266
ID2     3762    62      1541
``````

Where `script.awk` is

``````{ printf("%s", \$1) }
{ for (i=4; i<=NF; i+=2) { printf("%s%d", OFS, \$i - \$(i-1) - \$(i-2)) } }
{ printf("%s", RS) }
``````

All blocks will be executed for each line of input from the file.

The first block outputs the ID.

The second block iterates over the fields as you described and outputs data separated by `OFS` (the output field separator, set to a tab on the command line).

The final block simply outputs the record separator `RS` which is a newline by default.

Alternatively,

``````BEGIN { OFS = "\t" }
{ printf("%s", \$1) }
{ for (i=4; i<=NF; i+=2) { printf("%s%d", OFS, \$i - \$(i-1) - \$(i-2)) } }
{ printf("%s", RS) }
``````

to get rid of the need for `-v OFS='\t'`.

As a "one-liner":

``````\$ awk 'BEGIN { OFS = "\t" }
{ printf("%s", \$1) }
{ for (i=4; i<=NF; i+=2) { printf("%s%d", OFS, \$i - \$(i-1) - \$(i-2)) } }
{ printf("%s", RS) }' file
``````

For the extended problem:

``````{ printf("%s", \$1) }
{ for (i=4; i<=NF; i+=2) { printf("%s%d%s%d", OFS, \$(i-1), OFS, \$i - \$(i-1) - \$(i-2)) } }
{ printf("%s%d%s%s", OFS, \$NF, OFS, RS) }
``````

This would generate the following from the original file directly:

``````ID1     234     76      392     266     470
ID2     176     3762    869     62      347     1541    231
``````

awk solution:

``````awk '{ r=\$1; for(i=4;i<=NF;i+=2) r=r"\t"\$i-\$(i-1)-\$(i-2); printf "%s\n",r }' OFS='\t' file
``````
• `r=\$1` - capturing the 1st field

• `for(i=4;i<=NF;i+=2)` - iterating through even fields

• `\$i-\$(i-1)-\$(i-2)` - performing the needed substraction

The output:

``````ID1 76  266
ID2 3762    62  1541
``````