Come prendere il valore assoluto usando awk?


14

Se ho sotto due date:

2015-09-12,2015-08-13

E ho bisogno di ottenere il numero di giorni tra di loro, userò il seguente codice:

awk -F'[-,]' '{print 360*($4-$1)+30*($5-$2)+($6-$3)}'

L'output per questo codice sarà -29mentre in realtà la differenza è29

Risposte:


23

Puoi definire funzioni awkcome:

awk -F'[-,]' '
  function abs(v) {return v < 0 ? -v : v}
  {print abs(360*($4-$1)+30*($5-$2)+($6-$3))}'

11

Il trucco comune per questo tipo di situazioni è usare la radice quadrata del quadrato:

awk -F'[-,]' '{print sqrt((360*($4-$1)+30*($5-$2)+($6-$3))^2)}'

3
Un po 'eccessivo però. Nota che sqrt(x^2)va bene, ma sqrt(x)^2può introdurre piccoli errori che possono causare sorprese. Per busybox awk, deve essere compilato con il supporto matematico abilitato (ad esempio non quello predefinito nei pacchetti Debian).
Stéphane Chazelas,

3
Sqrt (x) ^ 2 non fallirebbe semplicemente per i numeri negativi?
Daniel McLaury,

1
@DanielMcLaury Ecco perché sqrt(x^2).
jimmij,

@jimmij: sto rispondendo al commento sulla tua risposta, non alla risposta stessa.
Daniel McLaury,

3

Un altro modo:

awk -F'[-,]' '{d=360*($4-$1)+30*($5-$2)+($6-$3);print (d>0)?d:-d}'

Questa è probabilmente la risposta più efficiente (prestazioni).
Hastur,

2

Supponendo che tu sia su GNU awk, la mktimefunzione funky è utile qui.

awk -F, '{ gsub(/-/," ",$0);a=(mktime($2 " 23 59 59")-mktime($1 " 00 00 00"))/86400;print a*(a<0?-1:1)}' file.txt
29

1

Fino a tardi, ma qui è una soluzione che utilizza il datecomando GNU che non si basa su 30 giorni fissi ogni mese che tutte le risposte postate sopra lo consideravano ma la risposta di Steve .

awk -F, '{cmd="printf \"%d\n\" $((($(date -d"$1" +%s)-$(date -d"$2" +%s))/86400))"; 
    cmd|getline $0; $0*=($0<0?-1:1); close(cmd)}1' infile

Per l'input seguente:

2015-09-12,2015-08-13
2017-02-12,2017-03-12

L'output è:

30
28
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.