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
我有这个文件
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