Jak przyjąć wartość bezwzględną za pomocą awk?


14

Jeśli mam poniżej dwóch dat:

2015-09-12,2015-08-13

I muszę uzyskać liczbę dni między nimi, użyję poniższego kodu:

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

Dane wyjściowe dla tego kodu będą, -29podczas gdy tak naprawdę jest różnica29

Odpowiedzi:


23

Możesz zdefiniować funkcje w awk:

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

11

Typową sztuczką w tego rodzaju sytuacjach jest użycie pierwiastka kwadratowego z kwadratu:

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

3
Trochę przesada. Pamiętaj, że sqrt(x^2)jest w porządku, ale sqrt(x)^2może wprowadzać drobne błędy, które mogą powodować niespodzianki. W przypadku busyboksa awknależy go zbudować z włączoną obsługą matematyczną (na przykład nie domyślną w pakietach Debiana).
Stéphane Chazelas

3
Czy sqrt (x) ^ 2 po prostu się nie powiedzie dla liczb ujemnych?
Daniel McLaury,

1
@DanielMcLaury Właśnie dlatego sqrt(x^2).
jimmij

@jimmij: Odpowiadam na komentarz do twojej odpowiedzi, a nie na samą odpowiedź.
Daniel McLaury

3

Inny sposób:

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

Jest to prawdopodobnie najbardziej wydajna odpowiedź (wydajność).
Hastur

2

Zakładając, że korzystasz z GNU awk, mktimeprzydatna jest tu funkcja funky .

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

Do późna, ale oto rozwiązanie wykorzystujące datepolecenie GNU, które nie opiera się na ustalonych 30 dniach każdego miesiąca, że ​​wszystkie powyższe odpowiedzi uważały to, ale odpowiedź Steve'a .

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

Dla poniższych danych wejściowych:

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

Dane wyjściowe to:

30
28
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.