Как взять абсолютное значение с помощью awk?


14

Если у меня есть ниже двух дат:

2015-09-12,2015-08-13

И мне нужно получить количество дней между ними, я буду использовать следующий код:

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

Выход для этого кода будет в то -29время как на самом деле разница29

Ответы:



11

Обычная хитрость для таких ситуаций - использование квадратного корня из квадрата:

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

3
Хотя немного излишне. Обратите внимание, что sqrt(x^2)это хорошо, но sqrt(x)^2может привести к небольшим ошибкам, которые могут вызвать сюрпризы. Для busybox awkего необходимо собрать с включенной поддержкой математики (например, не в пакетах Debian).
Стефан

3
Разве sqrt (x) ^ 2 просто не сработает для отрицательных чисел?
Даниэль МакЛори

1
@DanielMcLaury Вот почему это так sqrt(x^2).
Джимми

@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.