awk用于从logfile生成报告

时间:2016-05-24 11:44:16

标签: logging awk report data-manipulation

我有一个包含这些字符串的日志:

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还是最简单的方法是可能的吗?

2 个答案:

答案 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年份格式,以便您可以轻松按日期排序,但如果您愿意,可以按上述内容以适应。您需要添加逻辑来处理退出而无需输入或您需要识别/报告/处理的任何其他内容。