PHP dinamik bir metin listesi ayrıştırmak için en iyi yolu

3 Cevap php

Ben bir metin listesini aşağıda, bu EVE Online ve oyun içinde bir kişiyi öldürmek bu temelde size gönderilecek alır denilen popüler bir online oyun olan var. Ben ilgili tüm bilgileri ayıklamak için PHP kullanarak bu ayrıştırmak için bir araç inşa ediyorum. Ben gösterilen tüm bilgilerin parçaları ihtiyacınız olacak ve ben güzel alakalı kapsüllü veri haline kırmak için sınıfları yazma ediyorum.

2008.06.19 20:53:00

Victim: Massi
Corp: Cygnus Alpha Syndicate
Alliance: NONE
Faction: NONE
Destroyed: Raven
System: Jan
Security: 0.4
Damage Taken: 48436

Involved parties:

Name: Kale Kold
Security: -10.0
Corp: Vicious Little Killers
Alliance: NONE
Faction: NONE
Ship: Drake
Weapon: Hobgoblin II
Damage Done: 22093

Name: Harulth (laid the final blow)
Security: -10.0
Corp: Vicious Little Killers
Alliance: NONE
Faction: NONE
Ship: Drake
Weapon: Caldari Navy Scourge Heavy Missile
Damage Done: 16687

Name: Gistatis Tribuni / Angel Cartel
Damage Done: 9656

Destroyed items:

Capacitor Power Relay II, Qty: 2
Paradise Cruise Missile, Qty: 23
Cataclysm Cruise Missile, Qty: 12
Small Tractor Beam I
Alloyed Tritanium Bar, Qty: 2 (Cargo)
Paradise Cruise Missile, Qty: 1874 (Cargo)
Contaminated Nanite Compound (Cargo)
Capacitor Control Circuit I, Qty: 3
Ballistic Deflection Field I
'Malkuth' Cruise Launcher I, Qty: 3
Angel Electrum Tag, Qty: 2 (Cargo)

Dropped items:

Ballistic Control System I
Shield Boost Amplifier I, Qty: 2
Charred Micro Circuit, Qty: 4 (Cargo)
Capacitor Power Relay II, Qty: 2
Paradise Cruise Missile, Qty: 10
Cataclysm Cruise Missile, Qty: 21
X-Large Shield Booster II
Cataclysm Cruise Missile, Qty: 3220 (Cargo)
Fried Interface Circuit (Cargo)
F-S15 Braced Deflection Shield Matrix, Qty: 2
Salvager I
'Arbalest' Cruise Launcher I
'Malkuth' Cruise Launcher I, Qty: 2

Ben verileri ayrıştırmak için normal ifadeler kullanarak düşünüyordum ama bu nasıl yaklaşım? Bir tek satır dizeye postayı daraltmak ya da dizide her satırı ayrıştırmak misiniz? Sorun hesaba birkaç anomaliler söz konusudur.

İlk olarak, 'tarafların' bölümündeki dinamik ve aşağıdaki gibi tüm benzer yapıya sahip bir sürü insan içerebilir ancak bir bilgisayar kontrollü düşman çok kurbana bir çekim alırsa, yalnızca 'Adı' ve 'Hasar kısaltılmış olur Bitti 'alanlar, (Gistatis Tribuni / Melek Cartel) yukarıda gösterildiği gibi.

İkincisi, 'Tahrip' ve 'Bırakılan' öğeleri dinamik ve her postada farklı uzunluklarda olacak ve ben de onlar kargo olan miktar ve kurup veya almak gerekir.

Bir yaklaşım için fikirler bekliyoruz.

3 Cevap

Eğer esnek bir şey istiyorsanız, durum makinesi yaklaşım kullanın.

Eğer hızlı ve kirli bir şey istiyorsanız, regexp kullanın.

İlk çözüm için, bunu önemsiz bir görev değil çünkü parsin uzmanlaşmış kütüphaneleri kullanabilirsiniz. Ama bu oldukça basit bir biçimidir, çünkü örneğin, naif bir ayrıştırıcı kesmek olabilir:

<?php

class Parser 
{
   /* Enclosing the parser in a class is not mandatory but it' clean */

    function Parser()
    {

        /* data holder */
        $this->date = '';
        $this->parties = array();
        $this->victim = array();
        $this->items = array("Destroyed" => array(),
                                            "Dropped" => array());

        /* Map you states on actions. Sub states can be necessary (and sub parsers too :-) */                   
        $this->states = array('Victim' => 'victim_parsing',
                                             'Involved' => 'parties_parsing' ,
                                             'items:' => "item_parsing");


        $this->state = 'start';                      
        $this->item_parsing_state = 'Destroyed';     
        $this->partie_parsing_state = '';           
        $this->parse_tools = array('start' => 'start_parsing',
                                           'parties_parsing' =>'parties_parsing',
                                           'item_parsing' => 'item_parsing',
                                           'victim_parsing' => 'victim_parsing');


    }

    /* the magic job is done here */

    function checkLine($line) 
    {
        foreach ($this->states as $keyword => $state) 
            if (strpos($line, $keyword) !== False)
                    $this->state = $this->states[$keyword];

        return trim($line);
    }

    function parse($file)
    {
        $this->file = new SplFileObject($file);
        foreach ($this->file as $line) 
            if ($line = $this->checkLine($line))
                 $this->{$this->parse_tools[$this->state]}($line);
    }


    /* then here you can define as much as parsing rules as you want */

    function victim_parsing($line) 
    {
        $victim_caract = explode(': ', $line);
        $this->victim[$victim_caract[0]] = $victim_caract[1];
    }

    function start_parsing($line)
    {
        $this->date = $line;
    }

    function item_parsing($line) 
    {
        if (strpos($line, 'items:') !== False)
        {
            $item_state = explode(' ', $line);
            $this->item_parsing_state = $item_state[0];
        }   
          else 
         {
               $item_caract = explode(', Qty: ', $line);
               $this->items[$this->item_parsing_state][$item_caract[0]] = array();
               $item_infos =  explode(' ', $item_caract[1]);
               $this->items[$this->item_parsing_state][$item_caract[0]] ['qty'] = empty($item_infos[0]) ? 1 : $item_infos[0];
               $this->items[$this->item_parsing_state][$item_caract[0]] ['cargo'] = !empty( $item_infos[1]) ? "True":  "False";
               if  (empty( $this->items[$this->item_parsing_state][$item_caract[0]] ['qty'] ))
                print $line;
         }
    }

    function parties_parsing($line) 
    {        

        $partie_caract = explode(': ', $line);

        if ($partie_caract[0] == "Name")
        {
            $this->partie_parsing_state = $partie_caract[1];
            $this->parties[ $this->partie_parsing_state ] = array();
        }
        else
            $this->parties[ $this->partie_parsing_state ][$partie_caract[0]] = $partie_caract[1];

    }

}

/* a little test */

$parser = new Parser();
$parser->parse('test.txt');

echo "======== Fight report - ".$parser->date." ==========\n\n";
echo "Victim :\n\n";
print_r($parser->victim);
echo "Parties :\n\n";
print_r($parser->parties);
echo "Items: \n\n";
print_r($parser->items);

?>

Burada, güvenilirlik ve perf :-) bir sorun değil çünkü biz bunu yapabilir

Mutlu oyunu!

Herhalde sırayla her satır okuma ve mevcut durumuna bağlı olarak onunla ilgili bir durum makine yaklaşımı ile gitmek istiyorum.

"Bırakılan öğeler:" gibi bazı satırlar, öğeler olarak, aşağıdaki satırları yorumlamak neden durumunu değiştirebilir. "Tarafları okuma" devlet size kişi hakkında veri dizisi her satır ekleyerek olurdum ve sen boş bir satır okurken, size tam bir kayıt var biliyorum da.

İşte Graphviz yılında hamile bir kaba FSM bulunuyor

State Makinesi

Bazı kenarları boş satırları okurken gibi, kodunuzda eylemleri tetikleyecek.

Sen http://pear.php.net/package/PHP_LexerGenerator ilginizi çekebilir

(Evet, alfa bulunuyor. Evet, ben kendim kullanmadım. Evet, bilmeniz gereken / lexer sözdizimi öğrenmenize. Neden bunu öneriyorsunuz? Onunla deneyim ;-) ne olurdu Sadece merak)