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

AWK: How do I compute the total hours from a CSV file

我有这个文件

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为身份证号; 2 是执行的操作; 3 是确切的时间戳; 4 是四舍五入的时间。

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

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

获取总小时数,但我不知道应该如何开始。

我想得到这个输出:

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

其中字段 1 是 ID,字段 2 是计算的总时数。 另外,请注意,真实文件将是混乱的,并且不会像上面的示例那样排序。如果缺少任何必需的条目,即缺少一个超时等,它应该只打印它跳过了那个特定的 ID。

关于此的任何想法都将非常有帮助。 谢谢

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

如果给定 ISO 时间戳,我可能会为 return 纪元时间编写一个函数。纪元时间使算术变得容易。但它使用完整的时间戳,而不是您的舍入值。

function epoch_time(ts) {

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

    return mktime(ts)
}

假设我们可以依赖输入文件的格式——一个很大的假设——你可以使用非常简单的代码 select 并处理输入文件的每一行。

 == "Time-in" {
    timein = epoch_time()
}

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

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

所以完整的代码应该是这样的,

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

 == "Time-out" {
    timeout = epoch_time()
    # Add the result to any existing value for this id number.
    # Express in hours.
    output[] += (((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
$ cat tst.awk
BEGIN { FS="[-, :]" }
=="in"  { tin[]  +=  }
=="out" { tout[] +=  }
END {
    for (key in tin) {
        print key, tout[key] - tin[key]
    }
}

$ awk -f tst.awk file
001 13