Як прийняти абсолютне значення за допомогою awk?


14

Якщо у мене нижче двох побачень:

2015-09-12,2015-08-13

І мені потрібно отримати кількість днів між ними, я буду використовувати наступний код:

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

Вихід для цього коду буде, -29хоча насправді різниця29

Відповіді:


23

Ви можете визначити функції на awkзразок:

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

11

Загальна хитрість для подібних ситуацій полягає у використанні квадратного кореня квадрата:

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

3
Трохи надмірність, хоча. Зауважте, що sqrt(x^2)це добре, але sqrt(x)^2може ввести крихітні помилки, які можуть викликати сюрпризи. Для зайнятої скриньки awkїї потрібно будувати з увімкненою підтримкою з математики (не за замовчуванням, наприклад, у пакунках Debian).
Стефан Шазелас

3
Чи не буде sqrt (x) ^ 2 просто невдалим для від’ємних чисел?
Даніель Макларі

1
@DanielMcLaury Ось чому це так sqrt(x^2).
jimmij

@jimmij: Я відповідаю на коментар до вашої відповіді, а не на саму відповідь.
Даніель МакЛаурі

3

Інший спосіб:

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

Це, мабуть, найефективніша відповідь (продуктивність).
Хастури

2

Якщо припустити, що ви перебуваєте в GNU awk, mktimeфункціональна функція тут корисна.

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

До пізнього dateтерміну , але ось рішення з використанням команди GNU, яка не базується на фіксованих 30 днях щомісяця, що всі відповіді, розміщені вище, вважали це, а відповідь Стіва .

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

Для поданого нижче вводу:

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

Вихід:

30
28
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.