IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Isoler du texte entre balises


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 131
    Par défaut Isoler du texte entre balises
    Bonjour à tous,

    Après plusieurs jours de "brainstorming", je ne peux continuer à consacrer tout mon temps à une seule chose et il me faut bien me résoudre à solliciter de l'aide.

    Pour résumer, j'utilise Joomla 2.5.8 et j'ai un module qui affiche l"historique des événements d'un serveur de jeu Trackmania. L'affichage est en "brut" donc sous la forme (je n'ai mis qu'un exemple):

    [2013/03/27 14:20:29] [gc_server (TestServer_DontUse_Thx)] $z$s$i$ff0$o» $oIl n'y a pas assez de joueurs (au moins 2 joueurs)
    (Cela est stocké dans une variable $line que j'affiche juste avec un "echo" puis un retour de ligne pour séparer chaque ligne)

    Je voudrais ne conserver que ce qui est en gras :

    [2013/03/27 14:20:29] [gc_server (TestServer_DontUse_Thx)] $z$s$i$ff0$o» $oIl n'y a pas assez de joueurs (au moins 2 joueurs)
    ... et que l'affichage se présente comme ceci (ici les couleurs ne ressortent pas mais sur mon site il y a un fond contrasté):

    [2013/03/27 14:20:29]
    TestServer_DontUse_Thx
    Il n'y a pas assez de joueurs (au moins 2 joueurs)
    ... et dans la mesure où ce module n'est prévu que pour l'affichage d'un historique d'événements, je voudrais le modifier un peu (via une boucle) pour qu'il affiche les événements des autres serveurs de jeu que je vais ajouter, quel que soit leur nombre.

    Pourriez-vous m'aider à faire cela ?

    Un grand merci d'avance...

    Adgenodux

  2. #2
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 020
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 020
    Par défaut
    Bonjour,

    (je n'ai mis qu'un exemple)
    C'est bien là le problème! Comment veux tu que l'on puisse se faire une idée précise de tes lignes de log, si on ne sais pas si la partie $z$s$i$ff0$o» $o, par exemple, peut ou pas varier d'une ligne à l'autre?

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?php $log = <<<'EOD'
    [2013/03/27 16:39:18] [gc_server (TestServer_DontUse_Thx)] $z$s$i$ff0$o» $oIl n'y a pas assez de joueurs (au moins 2 joueurs)
    [2013/03/27 16:39:18] [gc_server (TestServer_DontUse_Thx)] $z$s$i$ff0$o» $oBegin Challenge
    [2013/03/27 16:39:17] Loading challenge A12-Speed.Challenge.Gbx (zwAbNlFSDcXjRBk0YSMyxc5kJJ8)... 
    [2013/03/27 16:39:17] [gc_server (TestServer_DontUse_Thx)] $z$s$i$ff0$o» $oEnd Challenge
    EOD;
    // pattern1 match uniquement la ligne que tu as montrée
    $pattern1 = '`^(?<datetime>\[.+]) \[gc_server \((?<gc_server>\w+)\)] \$z\$s\$i\$ff0\$o» \$o(?<message>.+)$`mU';
    // pattern2 match aussi la ligne 3
    $pattern2 = '`^(?<datetime>\[.+]) (?:(?:\[gc_server \((?<gc_server>\w+)\)] \$z\$s\$i\$ff0\$o» \$o(?<message>.+))|(?:(?<loading>.+) (?<code>\(.+)))$`mU'; //x';
     
    preg_match_all( $pattern1, $log, $matches1, PREG_SET_ORDER );
    preg_match_all( $pattern2, $log, $matches2, PREG_SET_ORDER );
     
    // on enlève les indexes numériques (pour la cosmétique)
    foreach ( $matches1 as &$match ) { for ($i = 0 ; $i < 6 ; $i++ ) { if (isset($match[$i])) unset( $match[$i] ); } }
    foreach ( $matches2 as &$match ) { for ($i = 0 ; $i < 6 ; $i++ ) { if (isset($match[$i])) unset( $match[$i] ); } }
    ?>
    <h3>pattern 1</h3><pre><?php print_r( $matches1 ); ?></pre>
    <h3>pattern 2</h3><pre><?php print_r( $matches2 ); ?></pre>

    Voilà, avec l'une de ces patterns tu peux extraire les informations qui t'intéressent. Après pour la mise en forme tu devrais pouvoir t'en sortir? non?

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 131
    Par défaut
    Bonjour et merci de ta réponse CosmoKnacki...

    Je n'ai volontairement pas mis trop de détails pour ne pas surcharger ma demande... j'ai donc considéré que les infos données suffisaient déjà à se faire une bonne idée, ce qui semble être le cas...

    La partie "Date" est reconnaissable à sa structure propre commençant par un crochet suivis de 4 chiffres + un slash etc... la partie "nom du serveur" commence toujours en étant précédée de la première ouverture de parenthèse de la ligne jusqu'à la première fermeture de parenthèse de la ligne et la 3ème et dernière partie commence après le "$z$s$i$ff0$o» $o" qui est en effet invariable, serveur par serveur (je ne l'ai en effet pas précisé) et se termine au prochain crochet qui contient la date de la ligne suivante et qui représente donc une nouvelle ligne...

    Pour distinguer les serveurs, il y a la partie entre la date et le nom public donné au serveur (qui n'est donc pas le même que son nom système) mais je ne l'ai pas mise en gras car elle ne doit servir qu'à distinguer les serveurs et non s'afficher, le nom public est là pour ça...

    J'arrive à me faire une idée de la structure mais comme il y a en plus des caractères spéciaux (crochets par ex), ça commence à faire compliqué pour mon niveau de connaissances d'utiliser les différents attributs possibles dans la réalisation de la regex utile...

    Je te remercie beaucoup pour ton aide, je vais m'atteler à cela et ferai un retour...

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 020
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 020
    Par défaut
    Pour ce qui est des caractères spéciaux (ie: caractères qui ont un sens particulier dans une regex), rien de bien compliqué, il suffit de les échapper avec \. C'est le cas pour [()$ pour ne citer que ceux présents dans $pattern1 et 2 (à noter qu'il est inutile d'échapper un crochet fermant sauf s'il doit être présent dans une classe de caractère, erreur souvent vue. Cela dit, le fait de l'échapper quand même ne change rien)

    Il serait intéressant de voir ce que d'autres serveurs (<--s=plusieurs) produisent en lieu et place de $z$s$i$ff0$o» $o pour éventuellement essayer de trouver des similitudes pouvant simplifier une regex plus générale acceptant des logs d'autres serveurs. N'hésites pas à les poster si tu en as d'autres.

  5. #5
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 020
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 020
    Par défaut
    En fait, si j'ai bien compris, tu reçois les lignes de log une par une dans ta variable $line?

    Dans ce cas l'idéal serait de faire une fonction utilisant preg_match (vu qu'il n'y a qu'une ligne preg_match_all n'est pas utile) et de créer des classes css avec les noms des champs nommés de la regex pour la mise en forme (en couleur dans le cas présent)

    Exemple :
    Code css : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <style type="text/css">
    .datetime { color: yellow; }
    .gc_server { color: purple; }
    .message { color: blue; }
    .loading, .code { color: grey; display: inline; }
    </style>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function display_log_line ($line) {
        preg_match('`^(?<datetime>\[.+\]) (?:(?:\[\w+ \((?<gc_server>\w+)\)] \$z\$s\$i\$ff0\$o» \$o(?<message>.+))|(?:(?<loading>.+) (?<code>\(.+)))$`mU', $line, $matches );
        foreach (array_keys($matches) as $key) {
            if (!is_numeric($key)) echo '<p class="' . $key . '">' . $matches[$key] . '</p>';
        }
    }

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 131
    Par défaut
    woaw super, merci CosmoKnacki

    ça c'est top... je regarderai tantôt (vu l'heure !) pour la signature d'un second serveur...

    En attendant, comme elle n'est pas très longue, voici ma procédure de récupération du log du premier serveur...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
     /* affichage de l'historique des événements */
     
    	// full path to text file
        define("TEXT_FILE", "/home/tadam/TMServeur/Logs/GameLog.gc_server.txt");
     
        // number of lines to read from the end of file
        define("LINES_COUNT", 50);
     
        function read_file($file, $lines) {
    		//global $fsize;
    		$handle = fopen($file, "r");
    		$linecounter = $lines;
    		$pos = -2;
    		$beginning = false;
    		$text = array();
    		while ($linecounter > 0) {
                $t = " ";
                while ($t != "\n") {
    				if(fseek($handle, $pos, SEEK_END) == -1) {
    					$beginning = true;
    					break;
    				}
    				$t = fgetc($handle);
    				$pos --;
                }
    			$linecounter --;
    			if ($beginning) {
    				rewind($handle);
                }
    			$text[$lines-$linecounter-1] = fgets($handle);
                if ($beginning) break;
    		}
    		fclose ($handle);
    		// return array_reverse($text);
    		return $text ;
        }
    	$fsize = round(filesize(TEXT_FILE)/1024/1024,2);
    	$lines = read_file(TEXT_FILE, LINES_COUNT);
    	foreach ($lines as $line) {
    	echo "$line";
    	echo "<br/><br/>";
    }
    Comme le nombre de serveurs sera variable et inconnu d'avance, je réfléchissais à créer un fichier log commun (en plus des respectifs) alimenté par un système de pipe par ex (comme tail -f). Ainsi pas besoin de chercher ailleurs si des logs à jour existent (un serveur pourrait rester plusieurs jours sans tourner, pas besoin donc d'afficher son log), je n'aurai qu'à configurer chaque nouveau serveur pour qu'il alimente le fichier commun en plus du sien quand il tourne.

    De plus, avec ce système, le fichier commun est alimenté selon les événements des serveurs de jeux en temps réel, ainsi peuvent se succéder des événements de tous les serveurs mélangés, contrairement à maintenant où on va rechercher les 50 dernières lignes du fichier pour les afficher... si j'ajoute un serveur, le système lira les logs de chaque serveur l'un après l'autre, donc d'abord 50 lignes du premier, puis 50 du second etc... moi je préfère que ce soit mélangé et fonction des événements...

    Là je vais "récupérer" un peu et j'attaque...

    Un très grand merci encore...

    Adgenodux

Discussions similaires

  1. Extraire un texte entre balises
    Par battl14 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 09/06/2009, 09h41
  2. Mettre du texte entre balises XML..?
    Par doudoubens dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 11/03/2009, 09h35
  3. [RegEx] Extraire un texte entres balises html ?
    Par booraq dans le forum Langage
    Réponses: 2
    Dernier message: 01/07/2007, 15h56
  4. Réponses: 1
    Dernier message: 26/05/2007, 17h23
  5. [RegEx] Comment récupérer du texte entre balises <font> ?
    Par leboy dans le forum Langage
    Réponses: 3
    Dernier message: 11/04/2007, 18h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo