2009-11-15 10 views
1

Я пытаюсь написать сценарий bash, чтобы проанализировать следующий файл журнала и дать мне список игроков CURRENT в комнате (поэтому игнорирование оставшихся игроков, включая игроков, которые, возможно, воссоединились) , Обратите внимание, что Самуэль вернулся.Разбор игроков в настоящее время в фойе

[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 

Чтобы дать мне список игроков, в настоящее время в комнате, как это (я, вероятно, может использовать тр для случая выключателя):

'jack','jones','samual' 

Когда игрок присоединяется он будет говорить «игрок [Playername | PlayerIP] вступил в игру "(вы можете игнорировать IP Когда игрок покидает он будет говорить." удаление игрок [Playername]: Некоторые Reason

Хотя я знаю, как добраться до обоих этих списков индивидуально, мне нужно объединить их, чтобы как-то выяснить, кто все еще находится в комнате, и порядок важен, потому что они могут воссоединиться. Кто-нибудь может мне с этим помочь?

У меня есть эта SED заявление, чтобы дать мне игроков, которые присоединились:

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

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

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

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

С благодарностью

ответ

3

Часть решения проблемы эффективно - это правильный инструмент. В этом случае, пытаясь сделать все это в Баш, вероятно, хуже, чем выбор что-то вроде 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 

и вы можете назвать это что-то вроде этого с вашего Баш скрипт:

tail -1000 ghost.log | ./analyse 

или даже:

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

Я пытался удержать Пе rl программа проста, насколько это разумно. Единственный «трудный» бит - это регулярное выражение. По существу, он перемещается по строкам ввода, пытаясь решить, представляет ли каждая строка кто-то, кто присоединяется или уходит. При присоединении имя пользователя добавляется в хэш-код %present; если он уходит, он удаляется. В конце имена указаны в порядке.

Достаточно ли этого, чтобы вернуть вас в нужное русло?

+0

Perl будет работать, но у меня нет никакого опыта с ним так потребуется большая помощь. Текущая форма скрипта захватывает последние 1000 строк активного файла журнала, называемого ghost.log. Затем он находит самую последнюю игру, к которой присоединился «Владелец», и отфильтровывает ее только до списка элементов, связанных с этим именем. Затем мне нужен список игроков, которые сейчас играют в игре, чем я. Оттуда мне нужно запросить мою базу данных sqlite3, где список имен является одним из операторов «где». Должен ли я использовать perl для всего этого? Или вы хотите, чтобы bash вызывал отдельный скрипт perl для синтаксического анализа? Как мне это сделать? – Dan

+0

Я смог прочитать большую часть этого. Я понимаю большую часть регулярного выражения тоже ... но что такое:? и:?. Почему средний паратезис не равен $ 2, а утверждение if истинно для строк, которые содержат это? Что представляют первые (/ и последние /)? – Dan

+1

ОК, первая '?:' Является частью конструкции '(?: ...)'. Это кластеризация, а не захват. Это означает, что содержимое обрабатывается как целое, но не присваивается переменной '$ 2'. Причина этого в том, что нам все равно, что такое контент, но мы хотим, чтобы следующий знак '?' Работал на весь фрагмент. Когда вы помещаете '?' После группы или одного символа, это говорит о том, что группа или символ являются необязательными. Здесь мы используем его, чтобы сказать, что wn IP-адрес (вещь в конструкции '(?: ...)' может присутствовать или отсутствовать. Кроме того, ':?' Позже: двоеточие может присутствовать или не присутствовать. – Tim

1

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

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

вы можете использовать поглазеть

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 

 Смежные вопросы

  • Нет связанных вопросов^_^