我有一个包含分隔符的列表|
40|192.168.1.2|user4
42|192.168.1.25|user2
58|192.168.1.55|user3
118|192.168.1.3|user11
67|192.168.1.25|user2
如您所见,我在字段42|192.168.1.25|user2
和字段67|192.168.1.25|user2
中拥有相同的IP。我怎样才能在它们之间添加这些线?你能用awk
给我一个解决方案吗?你能给我一些例子吗?
我需要一个像这样的结果:
40|192.168.1.2|user4
58|192.168.1.55|user3
109|192.168.1.25|user2
118|192.168.1.3|user11
你怎么看,我们已经计算了第一栏的数字。
答案 0 :(得分:1)
如果您需要输出与Input_file相同的顺序,那么关注awk
可能对您有帮助。
awk -F"|" '!c[$2,$3]++{val++;v[val]=$2$3} {a[$2,$3]+=$1;b[$2,$3]=$2 FS $3;} END{for(j=1;j<=val;j++){print a[v[j]] FS b[v[j]]}}' SUBSEP="" Input_file
现在也添加非单线形式的解决方案。
awk -F"|" ' ##Making field separator as pipe(|) here for all the lines for Input_file.
!c[$2,$3]++{ ##Checking if array C whose index is $2,$3 is having its first occurrence in array c then do following.
val++; ##incrementing variable val value with 1 each time cursor comes here.
v[val]=$2$3 ##creating an array named v whose index is val and value is $2$3(second field 3rd field).
} ##Closing c array block here now.
{
a[$2,$3]+=$1; ##creating an array named a whose index is $2 $3 and incrementing its value with 1st field value and add in its same index values to get SUM.
b[$2,$3]=$2 FS $3;##create array b with index of $2$3 and setting its value to $2 FS $3, where FS is field separator.
} ##closing this block here.
END{ ##Starting awk code END bock here.
for(j=1;j<=val;j++){ ##starting a for loop here from variable named j value 1 to till value of variable val here.
print a[v[j]] FS b[v[j]] ##printing value of array a whose index is value of array v with index j, and array b with index of array v with index j here.
}}
' SUBSEP="" Input_file ##Setting SUBSEP to NULL here and mentioning the Input_file name here.
答案 1 :(得分:1)
短GNU datamash
+ awk
解决方案:
datamash -st'|' -g2,3 sum 1 <file | awk -F'|' '{print $3,$1,$2}' OFS='|'
g2,3
- 按第2和第3个字段分组(即 IP地址和用户ID )
sum 1
- 对分组记录中的第一个字段值求和
输出:
40|192.168.1.2|user4
109|192.168.1.25|user2
118|192.168.1.3|user11
58|192.168.1.55|user3
答案 2 :(得分:1)
修改示例数据以包含ip地址192.168.1.25
的不同用户:
$ cat ipfile
40|192.168.1.2|user4
42|192.168.1.25|user1 <=== same ip, different user
58|192.168.1.55|user3
118|192.168.1.3|user11
67|192.168.1.25|user9 <=== same ip, different user
一个简单的awk
脚本:
$ awk '
BEGIN { FS="|" ; OFS="|" }
{ sum[$2]+=$1 ; if (user[$2]=="") { user[$2]=$3 } }
END { for (idx in sum) { print sum[idx],idx,user[idx] } }
' ipfile
58|192.168.1.55|user3
40|192.168.1.2|user4
118|192.168.1.3|user11
109|192.168.1.25|user1 <=== captured first user id
BEGIN { FS="|" ; OFS="|" }
:定义输入和输出字段分隔符;在开始时执行一次sum[$2]+=$1
:将字段#1存储/添加到数组(由ip address == field#2索引);对数据文件中的每一行执行一次if ....
:如果用户尚未针对给定的IP地址存储,则立即存储;这样可以保存我们为给定IP地址找到的第一个用户ID;对数据文件中的每一行执行一次END { for .... / print ...}
:遍历数组索引,打印sum,ip地址和(第一个)用户ID;最后执行一次注意:原始问题没有提供分类要求;可以根据需要添加排序......
答案 3 :(得分:1)
awk
救援!
$ awk 'BEGIN {FS=OFS="|"}
{a[$2 FS $3]+=$1}
END {for(k in a) print a[k],k}' file | sort -n
40|192.168.1.2|user4
58|192.168.1.55|user3
109|192.168.1.25|user2
118|192.168.1.3|user11
如果用户*不是密钥的一部分,并且您想要捕获第一个值
$ awk 'BEGIN {FS=OFS="|"}
{c[$2]+=$1;
if(!($2 in u)) u[$2]=$3} # capture first user
END {for(k in c) print c[k],k,u[k]}' file | sort -n
最终与@ markp的答案几乎相同。
答案 4 :(得分:1)
同一路径上的另一个想法,但允许不同的用户:
awk -F'|' '{c[$2] += $1}u[$2] !~ $3{u[$2] = (u[$2]?u[$2]",":"")$3}END{for(i in c)print c[i],i,u[i]}' OFS='|' input_file
如果有多个用户,他们将用逗号分隔