Разбор игроков в данный момент в лобби - PullRequest
1 голос
/ 16 ноября 2009

Я пытаюсь написать сценарий bash, чтобы разобрать следующий файл журнала и дать мне список ТЕКУЩИХ игроков в комнате (игнорируя игроков, которые ушли, но включая игроков, которые, возможно, присоединились). Обратите внимание, что Самуил вернулся.

[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 -n 's/\[.*\] \[GAME: .*\] player \[\(.*\)|.*\] joined the game/\1/p`

и это, чтобы дать мне список выпускников:

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

Но не знаете, как их объединить или поставить галочки и запятые в списке игроков.

Спасибо

Ответы [ 3 ]

3 голосов
/ 16 ноября 2009

Частью эффективного решения проблемы является выбор правильного инструмента. В этом случае попытка сделать все это в 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 голос
/ 16 ноября 2009

вы можете использовать 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
1 голос
/ 16 ноября 2009

Это может работать на то, что вы хотите. Предполагается, что, вероятно, небезопасно, что если игрок указан нечетное количество раз в комбинированных списках соединился и ушел, что он в данный момент находится в игре (например, присоединиться или присоединиться-покинуть объединение), в то время как четное число записей указывает, что ушел (например, присоединиться-оставить).

#!/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'
...