Awk Grep out设备id正在更改的用户
考虑以下日志:Awk Grep out设备id正在更改的用户,awk,sed,grep,Awk,Sed,Grep,考虑以下日志: tm=2017-08-29 11:25:33.579`user_id=1`device_id=1 tm=2017-08-29 11:25:35.961`user_id=1`device_id=1 tm=2017-08-29 11:25:38.961`user_id=2`device_id=2 tm=2017-08-29 11:25:40.993`user_id=2`device_id=2 tm=2017-08-29 11:25:41.729`user_id=3`device_id
tm=2017-08-29 11:25:33.579`user_id=1`device_id=1
tm=2017-08-29 11:25:35.961`user_id=1`device_id=1
tm=2017-08-29 11:25:38.961`user_id=2`device_id=2
tm=2017-08-29 11:25:40.993`user_id=2`device_id=2
tm=2017-08-29 11:25:41.729`user_id=3`device_id=3
tm=2017-08-29 11:25:46.075`user_id=3`device_id=4
.....(more logs)
如何将设备id正在更改的用户显示出来
我期望的结果是:
tm=2017-08-29 11:25:41.729`user_id=3`device_id=3
tm=2017-08-29 11:25:46.075`user_id=3`device_id=4
awk解决方案。我对这个问题的理解是:显示每个用户在设备上的每一个变化。我对输入文件做了一些更改:
$ cat ch.txt
tm=2017-08-29 11:25:33.579`user_id=1`device_id=1
tm=2017-08-29 11:25:35.961`user_id=1`device_id=1
tm=2017-08-29 11:25:38.961`user_id=2`device_id=2
tm=2017-08-29 11:25:38.961`user_id=2`device_id=1
tm=2017-08-29 11:25:40.993`user_id=2`device_id=2
tm=2017-08-29 11:25:40.993`user_id=2`device_id=1
tm=2017-08-29 11:25:41.729`user_id=3`device_id=3
tm=2017-08-29 11:25:46.075`user_id=3`device_id=4
$ cat tst.awk
BEGIN { FS="[[:space:]]+|`" }
!($3 in usr) { usr[$3] = $0; dev[$3] = $4 }
{
if ( $4 != dev[$3] ){ print usr[$3]; print $0; usr[$3] = $0; dev[$3] = $4 }
}
说明:
- FS=“[:space:][]+|`”:使用空格和`as字段分隔符
- 当您发现设备发生变化时
- 打印原始行usr[$3]
- 打印当前行$0
- 您需要在usr[$3]中保存当前行($0)
- 您需要在dev[$3]中保存当前设备($4)
$ awk -f tst.awk ch.txt
tm=2017-08-29 11:25:38.961`user_id=2`device_id=2
tm=2017-08-29 11:25:38.961`user_id=2`device_id=1
tm=2017-08-29 11:25:38.961`user_id=2`device_id=1
tm=2017-08-29 11:25:40.993`user_id=2`device_id=2
tm=2017-08-29 11:25:40.993`user_id=2`device_id=2
tm=2017-08-29 11:25:40.993`user_id=2`device_id=1
tm=2017-08-29 11:25:41.729`user_id=3`device_id=3
tm=2017-08-29 11:25:46.075`user_id=3`device_id=4
编辑:我讨厌这个输出。如果我们将其更改为:
cat tst2.awk
BEGIN { FS="[[:space:]]+|`|=" }
!($5 in dev) { dev[$5] = $7 }
{
if ( $7 != dev[$5] ){
print $2 OFS $3 ": user " $5 " changed device from " dev[$5] " to " $7;
dev[$5] = $7
}
}
由此产生:
$ awk -f tst2.awk ch.txt
2017-08-29 11:25:38.961: user 2 changed device from 2 to 1
2017-08-29 11:25:40.993: user 2 changed device from 1 to 2
2017-08-29 11:25:40.993: user 2 changed device from 2 to 1
2017-08-29 11:25:46.075: user 3 changed device from 3 to 4
2017-08-29 11:25:33.579: user 1 changed device from 1 to 2
awk解决方案:
awk -F'[[:space:]]+|`|=' 'uid && $5==uid && $7!=did{ print r ORS $0 }
{ uid=$5; did=$7; r=$0 }' file
-复合字段分隔符-F'[:space:]+|```='
-捕获用户iduid=$5;did=7美元;r=$0
、设备iduid
和当前记录did
r
输出:
tm=2017-08-29 11:25:41.729`user_id=3`device_id=3
tm=2017-08-29 11:25:46.075`user_id=3`device_id=4
输入是否按用户id分组?输出是否必须有序?这是否必须在管道中工作,或者我们可以假设一个可查找的文件?哎呀,你忘记发布代码了。有代码总比没有代码好。即使您不知道如何编写程序,元代码也会演示您认为程序应该如何工作。试着向我们展示你到目前为止的工作,你期望的结果和你得到的结果,我们将帮助你解决这个问题。我们无法修复我们看不到的东西。如果您有一个序列,如
用户id=1设备id=1
,用户id=1设备id=2
,用户id=1设备id=1
,用户id=1设备id=1
?这些行中哪一行应该输出?@melpomene问得好。我已经把你的问题记在心里回答了。这提供了大量的输出。;-)至少OP可以建议在一行中添加更改的时间戳、用户id、设备发件人、设备收件人。这会做出一些假设,例如:没有id是0
。输入按用户id
分组。一行中最多有两行具有相同的用户id
(否则它将吞并或复制行)。您的构造!usr[$3]
和!dev[$3]
导致这些数组下标存在,如果数组内容是文本0
(仍然不是null),则可能会错误地计算这些下标。在awk中测试数组成员资格的更好方法是在usr中测试$3
。比较:echo 0|awk'{a[NF]=$1}a[NF]{print“yo”}
vsecho 0|awk'{a[NF]=$1}NF in a{print“yo”}
。。。而且,echo 0|awk'a[NF]{print“foo”}NF在{print“bar”}中
。请注意,此处似乎没有设置a[NF]
,但它是由第一个测试隐式设置的。可能不是这个特定数据集的一个因素,但好习惯是。。好。:)同意。我想是吧!dev[$3]只是一个输入错误+1.