Comment prendre la valeur absolue en utilisant awk?


14

Si j'ai moins de deux dates:

2015-09-12,2015-08-13

Et j'ai besoin d'obtenir le nombre de jours entre eux, j'utiliserai le code ci-dessous:

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

La sortie de ce code sera alors -29que la différence est29

Réponses:


23

Vous pouvez définir des fonctions awkcomme:

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

11

L'astuce courante pour ce genre de situations est d'utiliser la racine carrée du carré:

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

3
Un peu exagéré cependant. Notez que sqrt(x^2)c'est bien, mais sqrt(x)^2peut introduire de minuscules erreurs qui peuvent provoquer des surprises. Pour busybox awk, il doit être construit avec le support mathématique activé (pas la valeur par défaut dans les paquets Debian par exemple).
Stéphane Chazelas

3
Sqrt (x) ^ 2 n'échouerait-il pas simplement pour les nombres négatifs?
Daniel McLaury

1
@DanielMcLaury C'est pourquoi c'est le cas sqrt(x^2).
jimmij

@jimmij: Je réponds au commentaire de votre réponse, pas à la réponse elle-même.
Daniel McLaury

3

Autrement:

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

C'est probablement la réponse (la performance) la plus efficace.
Hastur

2

En supposant que vous êtes sur GNU awk, la mktimefonction funky est utile ici.

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

Trop tard, mais voici une solution utilisant la datecommande GNU qui n'est pas basée sur 30 jours fixes chaque mois que toutes les réponses postées ci-dessus la considéraient comme la réponse de 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

Pour l'entrée ci-dessous:

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

La sortie est:

30
28
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.