Awk kullanarak mutlak değer nasıl alınır?


14

İki tarihin altındaysa:

2015-09-12,2015-08-13

Ve aralarındaki gün sayısını almam gerekiyor, aşağıdaki kodu kullanacağım:

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

Bu kodun çıktısı -29aslında fark29

Yanıtlar:


23

İşlevleri aşağıdaki awkgibi tanımlayabilirsiniz :

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

11

Bu tür durumlar için ortak numara, karenin kare kökünü kullanmaktır:

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

3
Gerçi biraz overkill. Bunun sqrt(x^2)iyi olduğunu, ancak sqrt(x)^2sürprizlere neden olabilecek küçük hatalar getirebileceğini unutmayın. Meşgul kutusu için awk, matematik desteği etkinleştirilmiş olarak oluşturulması gerekir (örneğin Debian paketlerinde varsayılan değer değildir).
Stéphane Chazelas

3
Sqrt (x) ^ 2 sadece negatif sayılar için başarısız olmaz mı?
Daniel McLaury

1
@DanielMcLaury Bu yüzden sqrt(x^2).
jimmij

@jimmij: Cevabın kendisine değil, cevabınızdaki yoruma cevap veriyorum.
Daniel McLaury

3

Diğer yol:

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

Bu muhtemelen en verimli (performans) cevaptır.
Hastur

2

GNU'da olduğunuzu varsayarsak awk, funky mktimeişlevi burada işe yarar.

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

Geç, ancak burada dateher ay 30 gün sabit olmayan GNU komutunu kullanan bir çözüm var, yukarıda verilen tüm cevaplar bunu düşündü ama steve'nin cevabı .

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

Aşağıdaki giriş için:

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

Çıktı:

30
28
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.