AWK:如何计算CSV文件的总小时数

时间:2017-06-25 15:29:11

标签: csv awk gawk

我有这个文件读取

001,Time-in,2017-06-25 08:04:42,08:00:00,
001,Time-out,2017-06-25 17:04:42,17:00:00,
001,Time-in,2017-06-25 18:04:42,18:00:00,
001,Time-out,2017-06-25 22:04:42,22:00:00,
...

其中字段1是ID号; 2是执行的动作; 3是确切的时间戳; 4是四舍五入的时间。

我想根据字段4 计算每个ID的总小时数。我知道我可以使用公式

((Out2+Out1)-(In2+In1))
or
((Out1-In1)+(Out2-In2))

获得总小时数,但我对我应该如何开始感到困惑。

我想得到这个输出:

001,13
002,12
..,..
..,..

其中,字段1是ID,2是计算的总小时数。 此外,请注意,真实文件将是混乱的,不像上面的例子那样排序。如果缺少任何所需的条目,即缺少一次超时等,则应该打印它跳过该特定ID。

对此有任何想法都会非常有帮助。 感谢。

2 个答案:

答案 0 :(得分:1)

$ cat tst.awk
BEGIN { FS="[-, :]" }
$3=="in"  { tin[$1]  += $10 }
$3=="out" { tout[$1] += $10 }
END {
    for (key in tin) {
        print key, tout[key] - tin[key]
    }
}

$ awk -f tst.awk file
001 13

答案 1 :(得分:0)

(下面没有错误处理或错误恢复。)

在给定ISO时间戳的情况下,我可能会编写一个返回纪元时间的函数。大纪元时间使算术变得容易。但它使用完整的时间戳,而不是您的舍入值。

function epoch_time(ts) {

    gsub("-", " ", ts)
    gsub(":", " ", ts)

    return mktime(ts)
}

假设我们可以依赖输入文件的格式 - 一个大的假设 - 你可以使用非常简单的代码来选择和处理输入文件的每一行。

$2 == "Time-in" {
    timein = epoch_time($3)
}

$2 == "Time-out" {
    timeout = epoch_time($3)
    # Add the result to any existing value for this id number.
    # Express in hours.
    output[$1] += (((timeout - timein) / 60) / 60)
}

END {
    for (key in output) print key, output[key] 
}

所以完整的代码看起来像这样,

# timestamp.awk
#
$2 == "Time-in" {
    timein = epoch_time($3)
}

$2 == "Time-out" {
    timeout = epoch_time($3)
    # Add the result to any existing value for this id number.
    # Express in hours.
    output[$1] += (((timeout - timein) / 60) / 60)
}

END {
    for (key in output) print key, output[key] 
}

function epoch_time(ts) {

    gsub("-", " ", ts)
    gsub(":", " ", ts)

    return mktime(ts)
}

。 。 。我会这样称呼它。

$ awk -F, -f timestamp.awk datafilename

对于这些数据,我得到了更远的输出。

001,Time-in,2017-06-25 08:04:42,08:00:00,
001,Time-out,2017-06-25 17:04:42,17:00:00,
001,Time-in,2017-06-25 18:04:42,18:00:00,
001,Time-out,2017-06-25 22:04:42,22:00:00,

002,Time-in,2017-06-25 09:04:42,08:00:00,
002,Time-out,2017-06-25 17:04:42,17:00:00,
002,Time-in,2017-06-25 19:04:42,18:00:00,
002,Time-out,2017-06-25 22:04:42,22:00:00,
$ awk -F, -f timestamp.awk datafilename
002 11
001 13