解析目前在大厅的球员

时间:2009-11-15 21:45:43

标签: bash parsing sed

我正在尝试编写一个bash脚本来解析以下日志文​​件并给我一个房间中的CURRENT玩家列表(因此忽略了离开的玩家,但包括可能重新加入的玩家)。请注意,Samual已重新加入。

[Sun Nov 15 14:12:50 2009] [GAME: Tower Defense Join Fast!] player [Samual|192.168.1.115] joined the game
[Sun Nov 15 14:12:54 2009] [GAME: Tower Defense Join Fast!] deleting player [Samual]: has left the game voluntarily
[Sun Nov 15 14:12:57 2009] [GAME: Tower Defense Join Fast!] player [Jack|192.168.1.121] joined the game
[Sun Nov 15 14:13:04 2009] [GAME: Tower Defense Join Fast!] player [NoobLand|192.168.1.153] is trying to join the game but is banned by IP address
[Sun Nov 15 14:13:04 2009] [GAME: Tower Defense Join Fast!] [Local]: User [NoobLand] was banned on server [www.example.com] on 2009-11-04 by [Owner] because [].
[Sun Nov 15 14:13:13 2009] [GAME: Tower Defense Join Fast!] player [Jones|192.168.1.178] joined the game
[Sun Nov 15 14:13:21 2009] [GAME: Tower Defense Join Fast!] player [Arnold|192.168.1.126] joined the game
[Sun Nov 15 14:13:35 2009] [GAME: Tower Defense Join Fast!] [Local]: Autokicking player [Arnold] for excessive ping of 131.
[Sun Nov 15 14:13:35 2009] [GAME: Tower Defense Join Fast!] deleting player [Arnold]: was autokicked for excessive ping of 131
[Sun Nov 15 14:13:44 2009] [GAME: Tower Defense Join Fast!] [Lobby] [Jones]: !chekme
[Sun Nov 15 14:13:44 2009] [GAME: Tower Defense Join Fast!] non-spoofchecked user [Jones] sent command [chekme] with payload []
[Sun Nov 15 14:13:45 2009] [GAME: Tower Defense Join Fast!] [Local]: Waiting for 4 more players before the game will automatically start.
[Sun Nov 15 14:14:05 2009] [GAME: Tower Defense Join Fast!] player [Samual|192.168.1.116] joined the game

给我一​​个目前在房间里的球员名单(我可以使用tr进行表壳切换):

'jack','jones','samual'

当玩家加入游戏时会说“玩家[玩家名称 | PlayerIP ]加入游戏”(你可以忽略IP。 当玩家离开时会说“删除玩家[玩家名称]:某些原因

虽然我知道如何单独获取这两个列表,但我需要将它们组合起来以某种方式弄清楚谁还在房间里,并且订单很重要因为它们可以重新加入。任何人都可以帮我这个吗?

我有这个sed声明给我加入的玩家:

sed -n 's/\[.*\] \[GAME: .*\] player \[\(.*\)|.*\] joined the game/\1/p`

这是给我一份离职者名单:

sed -n 's/\[.*\] \[GAME: .*\] deleting player \[\(.*\)\].*/\1/p'

但是不知道如何将两者结合起来,或者将标记和逗号放在玩家列表中。

由于

3 个答案:

答案 0 :(得分:3)

有效解决问题的一部分是选择合适的工具。在这种情况下,尝试在bash中完成所有操作可能是比Perl或Python更糟糕的选择,因为:

  • 实施,调试和维护会更复杂
  • 它将使用更多进程
  • 表现可能不佳

如果您希望以更合适的语言提供帮助,请询问。

...后...

好的,你选择了Perl ......

你当然可以做你在Perl中尝试做的所有事情。然而,由于你不熟悉它,我已经制作了一个小玩具程序,应该做你想要的。

#!/usr/bin/perl -w

use strict;

my %present;

while (<>) {  # loop over input lines
  if (/player \[(.*?)(?:\|\d+\.\d+\.\d+\.\d+)?\]:? (.*)/) {
    my $player = $1;
    my $event = $2;

    if ($event eq "joined the game") {
      $present{$player} = 1;
    } elsif ($event eq "has left the game voluntarily") {
      delete $present{$player};
    } elsif ($event =~ /^was autokicked/) {
      delete $present{$player};
    }
  }
}

foreach (sort keys %present) {
  print "$_\n";
}

产生的输出如下:

$ ./analyse inputfile
Jack
Jones
Samual

你可能希望从你的bash脚本中调用它:

tail -1000 ghost.log | ./analyse

甚至:

playerspresent=`tail -1000 ghost.log | ./analyse`

我试图让Perl程序尽可能简单明了。唯一的“困难”位是正则表达式。从本质上讲,它会循环输入线,试图决定每一行是代表某人加入还是离开。如果加入,则将用户名添加到%present哈希;如果离开,它将被删除。最后,名称按顺序列出。

这足以让你回到正轨吗?

答案 1 :(得分:1)

这可能适用于您想要的效果。它可能不安全地假定,如果一个玩家在联合加入和左侧列表中被列出奇数次他当前在游戏中(例如加入或加入 - 离开 - 加入),而偶数条目表示他离开了(例如,加入 - 离开)。

#!/bin/bash
joined=$(sed -n 's/\[.*\] \[GAME: .*\] player \[\(.*\)|.*\] joined the game/\1/p' gamefile.txt)

left=$(sed -n 's/\[.*\] \[GAME: .*\] deleting player \[\(.*\)\].*/\1/p' gamefile.txt)

saveIFS="$IFS"
IFS=$'\n'
players=("$(echo -e "$joined\n$left" | sort | uniq -c)")
IFS="$saveIFS"

flag=0
echo -n "'"
for i in "${players[@]}"
do
    if [[ $flag == 1 ]]
    then
        echo -n "', '"
    fi
    j=($i)
    if (( ${j[0]}%2 == 1 ))
    then
        flag=1
        echo -n "${j[1]}"
    fi
done
echo "'"

示例数据的结果:

'Jack', 'Jones', 'Samual'

答案 2 :(得分:1)

你可以使用gawk

awk '$11=="player" && ( $(NF-2)=="joined" || $12=="[Lobby]" ) {
 gsub(/\[|\|.*\]|:/,"",$12) ; player[$12]
}
$11=="deleting"{gsub(/\[|\]|:/,"",$13); delete player[$13]  }
END{
 for(i in player){  print i }
}' file

输出

./shell.sh
Jones
Samual
Jack