Wie nehme ich den absoluten Wert mit awk?


14

Wenn ich unter zwei Daten habe:

2015-09-12,2015-08-13

Und ich muss die Anzahl der Tage zwischen ihnen erhalten, ich werde den folgenden Code verwenden:

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

Die Ausgabe für diesen Code erfolgt, -29während der Unterschied tatsächlich ist29

Antworten:


23

Sie können Funktionen awkwie folgt definieren :

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

11

Der übliche Trick für diese Art von Situationen besteht darin, die Quadratwurzel des Quadrats zu verwenden:

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

3
Ein bisschen übertrieben. Beachten Sie, dass dies sqrt(x^2)in Ordnung ist, jedoch zu sqrt(x)^2winzigen Fehlern führen kann, die Überraschungen verursachen können. Für busybox awkmuss es mit aktivierter mathematischer Unterstützung erstellt werden (nicht die Standardeinstellung in Debian-Paketen zum Beispiel).
Stéphane Chazelas

3
Würde sqrt (x) ^ 2 nicht einfach für negative Zahlen scheitern?
Daniel McLaury

1
@DanielMcLaury Deshalb ist es sqrt(x^2).
Jimmy

@jimmij: Ich antworte auf den Kommentar zu Ihrer Antwort, nicht auf die Antwort selbst.
Daniel McLaury

3

Ein anderer Weg:

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

Dies ist wahrscheinlich die effizienteste (Leistungs-) Antwort.
Hastur

2

Vorausgesetzt, Sie sind auf GNU awk , dann ist die Funky- mktimeFunktion hier nützlich.

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

Zu spät, aber hier ist eine Lösung, die den GNU- dateBefehl verwendet, der nicht auf festen 30 Tagen pro Monat basiert, sondern auf der Antwort von 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

Für die folgende Eingabe:

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

Die Ausgabe ist:

30
28
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.