如何使用awk取绝对值?


14

如果我有以下两个日期:

2015-09-12,2015-08-13

我需要获取它们之间的天数,我将使用以下代码:

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

这段代码的输出-29实际上是29

Answers:


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
虽然有点矫kill过正。请注意,这sqrt(x^2)很好,但是sqrt(x)^2会引入微小的错误,可能会导致意外情况。对于busybox awk,需要在启用数学支持的情况下进行构建(例如,不是Debian软件包中的默认设置)。
斯特凡Chazelas

3
sqrt(x)^ 2不会仅因负数而失败吗?
Daniel McLaury

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,则funky 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

到目前为止,这是一个使用GNU date命令的解决方案,它不是基于每月固定的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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.