gpt4 book ai didi

linux - Awk:给定具有 session 数据的用户列表,输出具有特定数据的用户列表

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:41:12 24 4
gpt4 key购买 nike

不确定如何提出这个问题,因此我不知道如何在 google 或 SO 上搜索它。让我向您展示给定的数据。顺便说一下,这只是一个 Awk 练习,不是家庭作业。现在已经尝试断断续续地解决这个问题 2 天了。下面是一个例子;

Mon Sep 15 12:17:46 1997
User-Name = "wynng"
NAS-Identifier = 207.238.228.11
NAS-Port = 20104
Acct-Status-Type = Start
Acct-Delay-Time = 0
Acct-Session-Id = "239736724"
Acct-Authentic = RADIUS
Client-Port-DNIS = "3571800"
Framed-Protocol = PPP
Framed-Address = 207.238.228.57

Mon Sep 15 12:19:40 1997
User-Name = "wynng"
NAS-Identifier = 207.238.228.11
NAS-Port = 20104
Acct-Status-Type = Stop
Acct-Delay-Time = 0
Acct-Session-Id = "239736724"
Acct-Authentic = RADIUS
Acct-Session-Time = 115
Acct-Input-Octets = 3915
Acct-Output-Octets = 3315
Acct-Input-Packets = 83
Acct-Output-Packets = 66
Ascend-Disconnect-Cause = 45
Ascend-Connect-Progress = 60
Ascend-Data-Rate = 28800
Ascend-PreSession-Time = 40
Ascend-Pre-Input-Octets = 395
Ascend-Pre-Output-Octets = 347
Ascend-Pre-Input-Packets = 10
Ascend-Pre-Output-Packets = 11
Ascend-First-Dest = 207.238.228.255
Client-Port-DNIS = "3571800"
Framed-Protocol = PPP
Framed-Address = 207.238.228.57

所以日志文件包含了不同用户的上述数据。我特地粘贴了这个来表明这个用户有一个登录,Acct-Status-Type = Start,和一个注销,Acct-Status-Type = Stop。这算作一个 session 。因此我需要生成以下输出。

User:           "wynng"
Number of Sessions: 1
Total Connect Time: 115
Input Bandwidth Usage: 83
Output Bandwidth Usage: 66

我遇到的问题是以某种方式将信息附加到用户身上。当 session 处于停止状态时,日志文件中的每个条目都有相同的信息,所以我不能只使用正则表达式

/Acct-Input-Packets/{inPackets =$3}

/Acct-Output-Packets/{outPackets = $3}

数据的每次迭代都会覆盖过去的值。 我想做的是,如果我找到一个用户名条目并且这个条目有一个停止,那么我想为那个用户记录输入/输出数据包值。这就是我被难住的地方。

对于 session 值,我正在考虑将用户名保存在一个数组中,然后在 END{} 中计算重复项并将大于 2 的那些除以 2(如果偶数)。如果是奇数,则除以二然后将其减去。

我不一定想要答案,但可能需要一些提示/指导,或者可能是一个我可以扩展的简单示例。

最佳答案

您可以检查每一行:

  • 日期模式:/\w+\s\w+\s[0-9]{2}\s[0-9]{2}:[0-9]{2}:[0- 9]{2}\s[0-9]{4}/
  • 用户名值:/User-Name\s+=\s+\"\w+\"/
  • 状态值:/Acct-Status-Type\s+=\s+\w+/
  • 输入数据包值:/Acct-Input-Packets\s+=\s[0-9]+/
  • 输出包值:/Acct-Output-Packets\s+=\s[0-9]+/
  • 一个空行:/^$/

一旦您定义了要查找的内容(上述模式),这只是条件问题并将所有这些数据存储在某个数组中。

在下面的示例中,我将上面的每个值类型存储在每个类型的专用数组中,并带有一个 count 索引,该索引在空行 /^$/ 时递增被检测到:

awk 'BEGIN{
count = 1;
i = 1;
}{
if ($0 ~ /\w+\s\w+\s[0-9]{2}\s[0-9]{2}:[0-9]{2}:[0-9]{2}\s[0-9]{4}/){
match($0, /\w+\s(\w+)\s([0-9]{2})\s([0-9]{2}):([0-9]{2}):([0-9]{2})\s([0-9]{4})/, n);
match("JanFebMarAprMayJunJulAugSepOctNovDec",n[1])
n[1] = sprintf("%02d",(RSTART+2)/3);
arr[count]=mktime(n[6] " " n[1] " " n[2] " " n[3] " " n[4] " " n[5]);
order[i]=count;
i++;
}
else if ($0 ~ /User-Name\s+=\s+\"\w+\"/){
match($0, /User-Name\s+=\s+\"(\w+)\"/, n);
name[count]=n[1];
}
else if ($0 ~ /Acct-Status-Type\s+=\s+\w+/){
match($0, /Acct-Status-Type\s+=\s+(\w+)/, n);
status[count]=n[1];
}
else if ($0 ~ /^$/){
count++;
}
else if ($0 ~ /Acct-Input-Packets\s+=\s[0-9]+/){
match($0, /Acct-Input-Packets\s+=\s([0-9]+)/, n);
input[count]=n[1];
}
else if ($0 ~ /Acct-Output-Packets\s+=\s[0-9]+/){
match($0, /Acct-Output-Packets\s+=\s([0-9]+)/, n);
output[count]=n[1];
}
}
END{
for (i = 1; i <= length(order); i++) {

val = name[order[i]];

if (length(user[val]) == 0) {

valueStart = "0";

if (status[order[i]] == "Start"){
valueStart = arr[order[i]];
}
user[val]= valueStart "|0|0|0|0";
}
else {
split(user[val], nameArr, "|");

if (status[order[i]]=="Stop"){
nameArr[2]++;
nameArr[3]+=arr[order[i]]-nameArr[1]
}
else if (status[order[i]] == "Start"){
# store date start
nameArr[1] = arr[order[i]];
}

nameArr[4]+=input[order[i]];

nameArr[5]+=output[order[i]];

user[val]= nameArr[1] "|" nameArr[2] "|" nameArr[3] "|" nameArr[4] "|" nameArr[5];
}
}

for (usr in user) {
split(user[usr], usrArr, "|");
print "User: " usr;
print "Number of Sessions: " usrArr[2];
print "Total Connect Time: " usrArr[3];
print "Input Bandwidth Usage: " usrArr[4];
print "Output Bandwidth Usage: " usrArr[5];
print "------------------------";

}
}' test.txt

使用 match 函数提取值,例如:

match($0, /User-Name\s+=\s+\"(\w+)\"/, n);

对于日期,我们必须解析月份字符串部分,我使用了 this post 中的解决方案像这样提取:

match($0, /\w+\s(\w+)\s([0-9]{2})\s([0-9]{2}):([0-9]{2}):([0-9]{2})\s([0-9]{4})/, n);
match("JanFebMarAprMayJunJulAugSepOctNovDec",n[1])
n[1] = sprintf("%02d",(RSTART+2)/3);

收集到的值的所有处理都在 END 子句中完成,我们必须在其中对值进行分组,我创建了一个 user 数组,其中包含 username 作为键和值由 | 分隔的所有不同类型的串联:

[startDate] "|" [sessionNum] "|" [connectionTime] "|" [inputUsage] "|" [outputUsage]

this data input (您的数据已扩展),它给出:

User: TOTO
Number of Sessions: 1
Total Connect Time: 114
Input Bandwidth Usage: 83
Output Bandwidth Usage: 66
------------------------
User: wynng
Number of Sessions: 2
Total Connect Time: 228
Input Bandwidth Usage: 166
Output Bandwidth Usage: 132
------------------------

关于linux - Awk:给定具有 session 数据的用户列表,输出具有特定数据的用户列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42610749/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com