#!/usr/bin/awk -f ### diff.awk # numerical diff along columns BEGIN { OFS = FS # OFMT = "%.9g" sign = "[+-]?" decimal = "[0-9]+[.]?[0-9]*" fraction = "[.][0-9]*" exponent = "([Ee]" sign "[0-9]+)?" number = "^" sign "(" decimal "|" fraction ")" exponent "$" } NR == 1 { # orig data columns for (n=1; n<=NF; n++) { if ($n !~ number) { header[n] = $n dheader[n] = "d" $n } else { header[n] = "col" n dheader[n] = "dcol" n } printf(header[n]) printf(OFS) } # diff columns for (n=1; n<=NF; n++) { printf(dheader[n]) printf(n < NF ? OFS : ORS) } } NF { if (NF > nf_max) nf_max = NF # data columns for (n=1; n<=nf_max; n++) { if ($n == header[n] || $n == dheader[n]) continue if ($n ~ number) printf(OFMT, $n) else printf("") printf(OFS) } # diff columns for (n=1; n<=nf_max; n++) { if ($n == header[n] || $n == dheader[n]) continue if ($n ~ number) { data[n] = $n if (data_prev[n] ~ number) diff[n] = data[n] - data_prev[n] else diff[n] = "" data_prev[n] = data[n] } printf(diff[n]) printf(n < nf_max ? OFS : ORS) } }