我有一个包含这些字符串的日志:
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)
获得这样的东西?(也许我可以生成一个带有id;用户名的csv表)
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还是最简单的方法是可能的吗?
答案 0 :(得分:0)
Awk有一个数据结构arrays,它基本上是从字符串到Awk值的字典。数组总是一维的,但你可以通过在索引中编写逗号来“欺骗”,默认情况下扩展为变量SUBSEP(下标分隔符)的值"\034"
。因此arr["foo", "bar", "zonk"]
与撰写arr["foo" SUBSEP "bar" SUBSEP "zonk"]
相同。
由于您无法扫描数组以查找特定下标的所有键,因此在您的应用程序中,您可能希望填写一个退出/输入日期表以及其他表格,以便您了解哪些出口位于哪个人
假设您已经将一行划分为字段并将其转换为适当的值,这可能如下所示:
/* 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])
}
}
}
希望这为您提供了生成所需特定输出格式的方向。
AWK编程语言是一本出色的书,由该语言的创建者详细介绍了这一任务。如果你有机会,我强烈建议你阅读它。 编辑:Ed Morton指出,这本书已经过时了,推荐Arnold Robbins撰写的Effective Awk Programming,第4版。我从AWK PL中学到了,所以我不知道现代Awk的几个相关特征。
答案 1 :(得分:0)
这里开始使用GNU awk为第3个arg匹配()和真正的多维数组:
$ cat tst.awk
BEGIN { OFS="," }
NR==FNR { id2nm[$1] = $2; next }
match($0,/(.{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和名称分隔成某种标题,并且您应该使用YYYYMMDD年份格式,以便您可以轻松按日期排序,但如果您愿意,可以按上述内容以适应。您需要添加逻辑来处理退出而无需输入或您需要识别/报告/处理的任何其他内容。