用于从日志文件生成报告的 awk
awk for generating Report from logfile
我有一个包含如下字符串的日志:
1001031075825052016
1001041080225052016
1001030125825052016
1001031140325052016
1001040180025052016
1001030180125052016
1001031075926052016
1001041080226052016
1001030125926052016
1001031140126052016
1001030180026052016
1001030180026052016
其中:
前6个字符是id,第7个字符如果有人进入则等于1,如果有人离开则为0,从第8到11个字符是小时,最后一个字符是日期。
示例:
1001030180015062016
表示:用户 100103 在 2016 年 6 月 15 日 18:00
退出 (0)
该文件包含多个用户的数据,可以包含一个或多个月的数据。
awk 是否可以像这样为每个用户和每个月(csv 或 excel 文件)生成报告?
USER:100103
Month: 05/2016
date enter exit enter exit enter exit enter exit
25/05/2016 07:58 12:58 14:03 18:01
26/05/2016 07:79 12:59 14:01 18:00 18:00
并且可以将用户名与 ID 相关联(例如 100103 = mike)
获得这样的东西?(也许我可以生成一个 csv table with id; username)
USER:100103 - Mike
Month: 05/2016
date enter exit enter exit enter exit enter exit
25/05/2016 07:58 12:58 14:03 18:01
26/05/2016 07:79 12:59 14:01 18:00 18:00
awk 是否可行或有最简单的方法?
Awk 有一种数据结构,arrays,它基本上是从字符串到 Awk 值的字典。数组始终是一维的,但您可以通过在索引中写入逗号来 "cheat",这会扩展为变量 SUBSEP(下标分隔符)的值,默认情况下 "4"
。所以 arr["foo", "bar", "zonk"]
和 arr["foo" SUBSEP "bar" SUBSEP "zonk"]
.
是一样的
由于您无法扫描数组以查找特定下标的所有键,因此在您的应用程序中,您可能希望填写 table 个 exit/entry 日期加上额外的 table 让你知道哪个出口是哪个人的。
假设您已经将一行拆分为字段并将它们转换为适当的值,这可能如下所示:
/* assuming `user` is set to the six-digit ID code,
`datetime` is set to whichever format you prefer,
`direction` is one of "enter" or "exit" */
{
i = ++nr_access_by_user[user]
access_times[user, i] = datetime
access_direction[user, i] = direction
}
END
{
/* assuming you have already identified a specific value for `user`
whose activity you want to log, and a function called `relevant`
which determines if the access time comes from the day you want
to log */
for (i = 1; i <= nr_access_by_user[user]; i++)
{
if (relevant(access_times[user, i]))
{
print(access_times[user, i], access_direction[user, i])
}
}
}
希望这能为您提供生成所需特定输出格式的指导。
The AWK Programming Language 是该语言的创建者编写的一本优秀书籍,其中详细介绍了此类任务。如果你有机会,我强烈推荐阅读它。 编辑: Ed Morton 指出这本书已经严重过时,并推荐 Arnold Robbins 编写的 Effective Awk Programming,第 4 版。我是从 The AWK PL 学习的,所以可能有几个我不知道的现代 Awk 的相关特性。
这里开始使用 GNU awk 作为第三个参数来 match() 和 true multi-dimensional 数组:
$ cat tst.awk
BEGIN { OFS="," }
NR==FNR { id2nm[] = ; next }
match([=10=],/(.{6})(.)(.{4})(..)(..)(.*)/,a) {
id=a[1]; act=a[2]; time=a[3]; day=a[4]; mth=a[5]; yr=a[6]
sub(/../,"&:",time)
if (act == 1) {
++numEvents[id][yr][mth][day]
}
eventNr = numEvents[id][yr][mth][day]
events[id][yr][mth][day][eventNr][act] = time
}
END {
print "ID", "Name", "Year", "Month", "Day", "Enter", "Exit", "..."
for (id in events) {
for (yr in events[id]) {
for (mth in events[id][yr]) {
for (day in events[id][yr][mth]) {
printf "%s%s%s%s%s%s%s%s%s", id, OFS, id2nm[id], OFS, yr, OFS, mth, OFS, day
num = numEvents[id][yr][mth][day]
for (eventNr=1; eventNr<=num; eventNr++) {
enterTime = events[id][yr][mth][day][eventNr][1]
exitTime = events[id][yr][mth][day][eventNr][0]
printf "%s%s%s%s", OFS, enterTime, OFS, exitTime
}
print ""
}
}
}
}
}
.
$ awk -f tst.awk names log
ID,Name,Year,Month,Day,Enter,Exit,...
100103,Mike,2016,05,25,07:58,12:58,14:03,18:01
100103,Mike,2016,05,26,07:59,12:59,14:01,18:00
100104,Sue,2016,05,25,08:02,18:00
100104,Sue,2016,05,26,08:02,
$ awk -f tst.awk names log | column -s, -t
ID Name Year Month Day Enter Exit ...
100103 Mike 2016 05 25 07:58 12:58 14:03 18:01
100103 Mike 2016 05 26 07:59 12:59 14:01 18:00
100104 Sue 2016 05 25 08:02 18:00
100104 Sue 2016 05 26 08:02
恕我直言,你应该只生成 CSV,而不是将 ID 和名称分成某种 header,你应该使用 YYYYMMDD 年份格式,这样你就可以轻松地按日期排序,但你可以将上面的内容修改为如果你喜欢的话。您需要添加逻辑来处理没有进入的退出或您关心的任何其他事情identify/report/handle。
我有一个包含如下字符串的日志:
1001031075825052016
1001041080225052016
1001030125825052016
1001031140325052016
1001040180025052016
1001030180125052016
1001031075926052016
1001041080226052016
1001030125926052016
1001031140126052016
1001030180026052016
1001030180026052016
其中:
前6个字符是id,第7个字符如果有人进入则等于1,如果有人离开则为0,从第8到11个字符是小时,最后一个字符是日期。
示例:
1001030180015062016
表示:用户 100103 在 2016 年 6 月 15 日 18:00
退出 (0)
该文件包含多个用户的数据,可以包含一个或多个月的数据。
awk 是否可以像这样为每个用户和每个月(csv 或 excel 文件)生成报告?
USER:100103
Month: 05/2016
date enter exit enter exit enter exit enter exit
25/05/2016 07:58 12:58 14:03 18:01
26/05/2016 07:79 12:59 14:01 18:00 18:00
并且可以将用户名与 ID 相关联(例如 100103 = mike)
获得这样的东西?(也许我可以生成一个 csv table with id; username)
USER:100103 - Mike
Month: 05/2016
date enter exit enter exit enter exit enter exit
25/05/2016 07:58 12:58 14:03 18:01
26/05/2016 07:79 12:59 14:01 18:00 18:00
awk 是否可行或有最简单的方法?
Awk 有一种数据结构,arrays,它基本上是从字符串到 Awk 值的字典。数组始终是一维的,但您可以通过在索引中写入逗号来 "cheat",这会扩展为变量 SUBSEP(下标分隔符)的值,默认情况下 "4"
。所以 arr["foo", "bar", "zonk"]
和 arr["foo" SUBSEP "bar" SUBSEP "zonk"]
.
由于您无法扫描数组以查找特定下标的所有键,因此在您的应用程序中,您可能希望填写 table 个 exit/entry 日期加上额外的 table 让你知道哪个出口是哪个人的。
假设您已经将一行拆分为字段并将它们转换为适当的值,这可能如下所示:
/* assuming `user` is set to the six-digit ID code,
`datetime` is set to whichever format you prefer,
`direction` is one of "enter" or "exit" */
{
i = ++nr_access_by_user[user]
access_times[user, i] = datetime
access_direction[user, i] = direction
}
END
{
/* assuming you have already identified a specific value for `user`
whose activity you want to log, and a function called `relevant`
which determines if the access time comes from the day you want
to log */
for (i = 1; i <= nr_access_by_user[user]; i++)
{
if (relevant(access_times[user, i]))
{
print(access_times[user, i], access_direction[user, i])
}
}
}
希望这能为您提供生成所需特定输出格式的指导。
The AWK Programming Language 是该语言的创建者编写的一本优秀书籍,其中详细介绍了此类任务。如果你有机会,我强烈推荐阅读它。 编辑: Ed Morton 指出这本书已经严重过时,并推荐 Arnold Robbins 编写的 Effective Awk Programming,第 4 版。我是从 The AWK PL 学习的,所以可能有几个我不知道的现代 Awk 的相关特性。
这里开始使用 GNU awk 作为第三个参数来 match() 和 true multi-dimensional 数组:
$ cat tst.awk
BEGIN { OFS="," }
NR==FNR { id2nm[] = ; next }
match([=10=],/(.{6})(.)(.{4})(..)(..)(.*)/,a) {
id=a[1]; act=a[2]; time=a[3]; day=a[4]; mth=a[5]; yr=a[6]
sub(/../,"&:",time)
if (act == 1) {
++numEvents[id][yr][mth][day]
}
eventNr = numEvents[id][yr][mth][day]
events[id][yr][mth][day][eventNr][act] = time
}
END {
print "ID", "Name", "Year", "Month", "Day", "Enter", "Exit", "..."
for (id in events) {
for (yr in events[id]) {
for (mth in events[id][yr]) {
for (day in events[id][yr][mth]) {
printf "%s%s%s%s%s%s%s%s%s", id, OFS, id2nm[id], OFS, yr, OFS, mth, OFS, day
num = numEvents[id][yr][mth][day]
for (eventNr=1; eventNr<=num; eventNr++) {
enterTime = events[id][yr][mth][day][eventNr][1]
exitTime = events[id][yr][mth][day][eventNr][0]
printf "%s%s%s%s", OFS, enterTime, OFS, exitTime
}
print ""
}
}
}
}
}
.
$ awk -f tst.awk names log
ID,Name,Year,Month,Day,Enter,Exit,...
100103,Mike,2016,05,25,07:58,12:58,14:03,18:01
100103,Mike,2016,05,26,07:59,12:59,14:01,18:00
100104,Sue,2016,05,25,08:02,18:00
100104,Sue,2016,05,26,08:02,
$ awk -f tst.awk names log | column -s, -t
ID Name Year Month Day Enter Exit ...
100103 Mike 2016 05 25 07:58 12:58 14:03 18:01
100103 Mike 2016 05 26 07:59 12:59 14:01 18:00
100104 Sue 2016 05 25 08:02 18:00
100104 Sue 2016 05 26 08:02
恕我直言,你应该只生成 CSV,而不是将 ID 和名称分成某种 header,你应该使用 YYYYMMDD 年份格式,这样你就可以轻松地按日期排序,但你可以将上面的内容修改为如果你喜欢的话。您需要添加逻辑来处理没有进入的退出或您关心的任何其他事情identify/report/handle。