Bagaimana cara mengambil nilai absolut menggunakan awk?


14

Jika saya memiliki di bawah dua tanggal:

2015-09-12,2015-08-13

Dan saya perlu mendapatkan jumlah hari di antara mereka, saya akan menggunakan kode di bawah ini:

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

Output untuk kode ini akan -29sementara sebenarnya perbedaannya29

Jawaban:


23

Anda dapat mendefinisikan fungsi dalam awkseperti:

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

11

Trik umum untuk situasi seperti ini adalah menggunakan akar kuadrat dari bujur sangkar:

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

3
Tapi agak berlebihan. Perhatikan itu sqrt(x^2)baik-baik saja, tetapi sqrt(x)^2dapat memperkenalkan kesalahan kecil yang dapat menyebabkan kejutan. Untuk busybox awk, itu harus dibangun dengan dukungan matematika diaktifkan (bukan default dalam paket Debian misalnya).
Stéphane Chazelas

3
Tidakkah sqrt (x) ^ 2 gagal untuk angka negatif?
Daniel McLaury

1
@DanielMcLaury Itu sebabnya sqrt(x^2).
jimmij

@jimmij: Saya membalas komentar atas jawaban Anda, bukan jawaban itu sendiri.
Daniel McLaury

3

Cara lain:

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

Ini mungkin jawaban (kinerja) yang paling efisien.
Hastur

2

Dengan asumsi Anda menggunakan GNU awk, mktimefungsi funky berguna di sini.

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

Untuk terlambat, tapi di sini ada solusi menggunakan dateperintah GNU yang tidak didasarkan pada 30 hari tetap setiap bulan bahwa semua jawaban yang diposting di atas menganggapnya tetapi jawaban 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

Untuk input di bawah ini:

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

Outputnya adalah:

30
28
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.