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 :

Expression régulière vs explode


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier Avatar de PIEPLU
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    507
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 507
    Points : 92
    Points
    92
    Par défaut Expression régulière vs explode
    Bonjour tout le monde,


    Je dois décomposer des données de ce type :

    [1] => 178.255.215.78 - - [16/Mar/2013:03:00:32 +0100] "GET /saint-egreve-38120/homeopathe/ HTTP/1.1" 200 6886 "-" "Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)"
    De prime abord, je me serais lancé dans des explodes dans tous les sens.

    Puis, je me dis que des expressions régulières seraient peut être mieux.


    Qu'en pensez-vous ?


    Merci
    Vincent Pieplu
    Développeur Site Internet

  2. #2
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2004
    Messages : 108
    Points : 175
    Points
    175
    Par défaut
    Bonjour,

    Personnellement j'aurais sans hésité utilisé des expressions régulières . Il y a trop de caractères différents dans le schéma pour des explodes. De plus certains caractères comme dans l'adresses peuvent être différents (je pense particulièrement au "-" qui avec un explode va faire un peu n'importe quoi en cas de rencontre ).

  3. #3
    Membre régulier Avatar de PIEPLU
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    507
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 507
    Points : 92
    Points
    92
    Par défaut
    J'en suis ici pour le moment, mais je bloque

    http://regexr.com?345au
    Vincent Pieplu
    Développeur Site Internet

  4. #4
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 868
    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 : 2 868
    Points : 6 584
    Points
    6 584
    Par défaut
    Bonjour,

    j'aurais sans hésité utilisé des expressions régulières
    C'est clair et net!

    gskinner.com ça à l'air sympa comme outil en ligne. Bref!

    Ton code ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}) - - (.*]) "(.*/ HTTP\b)/gi
    ... (Je le post ici pour éviter d'avoir à changer de page en lisant le thread) ne marche pas car tu as commis quelques erreurs:

    - tu utilises / pour délimiter ton expression donc fatalement en arrivant à (.*/ le parser est persuadé que ton expression est terminée et que le H de HTTP\b)/gi est un nouveau modifier tout droit venu de la planète Zoltar. Donc soit tu échappes avec un antislash pour signifier que tu veux bien parler du caractère / et pas du délimiteur, soit tu choisis un autre délimiteur (+mieux) que tu es sûr de ne pas croiser toutes les trois secondes dans la chaîne à traiter. (par exemple ` ou #)
    - tu as pris le parti de ne pas vérifier si l'adresse ip est valide (ie: ce n'est pas le but) donc autant aller au plus court ((?:\d{1,3}\.){3}\d{1,3}) (au passage, on note que le point est échappé car il s'agit du caractère . et pas du caractère universel.)
    - le modifier g n'existe pas en PHP, la recherche global est déterminée par l'utilisation de preg_match_all.
    - le modifier i ne sert peut-être pas à grand chose dans le cas présent, autant s'en passer si toutes les lignes sont calibrées comme des tomates. (à voir)
    - tu devrais soit dégloutonner ponctuellement les quantifiers (* ou +) avec un ? (--> .*?) soit faire un dégloutonnage général en ajoutant le modifier U à la fin de la pattern.
    - préférer + à * si on est sûr d'avoir au moins un caractère
    Ce qui nous donne:
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    $string = <<<LOD
    178.255.215.78 - - [16/Mar/2013:03:00:32 +0100] "GET /saint-egreve-38120/homeopathe/ HTTP/1.1" 200 6886 "-" "Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)"
    143.212.13.18 - - [12/Jan/2056:07:13:32 +0100] "GET /sainte-benedicte-gardes-nous-du-mal-72143/rebouteux/ HTTP/1.1" 405 6886 "-" "Baiduspider ( http://www.baidu.com/search/spider.htm )"
    LOD;
    $pattern = '`((?:\d{1,3}\.){3}\d{1,3}) - - (.+]) "(.+/ HTTP)`U';
    preg_match_all( $pattern, $string, $matches );
    ?><pre><?php
    print_r( $matches);
    ?></pre>

    Bon courage pour la suite
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    34
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 34
    Points : 41
    Points
    41
    Par défaut
    Citation Envoyé par TERRA126 Voir le message
    Personnellement j'aurais sans hésité utilisé des expressions régulières .
    Pour moi, c'est totalement l'inverse :-)

    À première vue, c'est un log apache, cela se parse super bien avec un explode :

    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
     
    <?php
    $string = '178.255.215.78 - - [16/Mar/2013:03:00:32 +0100] "GET /saint-egreve-38120/homeopathe/ HTTP/1.1" 200 6886 "-" "Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)"';
     
    $explode = explode(' ', $string);
     
    // Données qui ne changeront jamais de place
    $ip = $explode[0];
    $date = $explode[3].' '.$explode[4];
    $method = $explode[5];
    $url = $explode[6];
    $version_http = $explode[7];
    $status_code = $explode[8];
    $size = $explode[9];
    $referer = $explode[10];
     
    // Pour le user agent, on récupére ce qui reste
    for ($i = 0; $i < 11; $i++) {
      unset($explode[$i]);
    }
    $user_agent = implode(' ', $explode);
     
    echo "
    ip : $ip
    date : $date
    method : $method
    url : $url
    version_http : $version_http
    status_code : $status_code
    size : $size
    referer : $referer
    user_agent : $user_agent
    ";

  6. #6
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2004
    Messages : 108
    Points : 175
    Points
    175
    Par défaut
    En fait pourquoi les regex ? parce que j'aurais plus tendance à vouloir récupérer les informations par domaine et ensuite m'occuper de chaque domaine un à un. Du moins c'est ce que je fais dans mes codes et je trouve que cela donne une bonne séparation des taches .

    De plus en faisant comme cela, se reporter à la doc apache est fait plutôt simplement :

    %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"
    devient donc :

    ^(\S+) \S+ \S+ \[([^\]]+)\] "([A-Z]+[^"]*)" \d+ \d+ "[^"]*" "([^"]*)"$
    Soit dit en passant je peux aussi récupérer les informations de manières segmenter en rajouter des groupes. Mais bon, après il existe plusieurs méthodes c'est vrai, savoir laquelle est la bonne est assez subjectif .

  7. #7
    Candidat au Club
    Inscrit en
    Mars 2013
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Mars 2013
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Tu peux aussi faire une recherche dans le string

  8. #8
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 868
    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 : 2 868
    Points : 6 584
    Points
    6 584
    Par défaut
    C'est vrai que mis à part le date_time et le referer, tout le reste se sépare bien de la même façon avec les espaces. Du coup, la description précise des séquences de caractères comme l'adresse ip perd de son intérêt.
    Il faut voir aussi qu'avec explode on se retrouve avec des " isolés dans les résultats à traiter avec trim et consortes.

    Maintenant un autre intérêt de preg_match_all est aussi d'obtenir un résultat facilement exploitable à l'aide de sous-masques nommés.
    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
    <?php $string = <<<LOD
    178.255.215.78 - - [16/Mar/2013:03:00:32 +0100] "GET /saint-egreve-38120/homeopathe/ HTTP/1.1" 200 6886 "-" "Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)"
    127.0.0.1 - - [20/Mar/2013:22:51:33 +0100] "GET /css/style.css HTTP/1.1" 200 1603 "http://truc/" "Opera/9.80 (X11; Linux x86_64; Edition Linux Mint) Presto/2.12.388 Version/12.12"
    127.0.0.1 - - [21/Mar/2013:07:39:31 +0100] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.2.22 (Ubuntu) (internal dummy connection)"
    LOD;
     
    // définition des champs utiles et du masque correspondant pour créer la pattern
    $fields = array( 'remote_host', 'log_name', 'user_id', 'date_time', 'request', 'method', 'request_url', 'protocol', 'status', 'size', 'referer', 'user_agent' );
    $mask = '`^(?<%s>.+) (?<%s>.+) (?<%s>.+) \[(?<%s>.+)] "(?<%s>(?<%s>.+) (?<%s>.+) (?<%s>.+))" (?<%s>.+) (?<%s>.+) "(?<%s>.+)" "(?<%s>.+)"$`Um';
    $pattern = vsprintf( $mask, $fields );
     
    preg_match_all( $pattern, $string, $matches, PREG_SET_ORDER );
     
    // récupération du résultat et élimination des variables inutiles
    $result = array();
    $fields = array_flip( $fields );
    foreach ($matches as $match) { $result[] = array_intersect_key( $match, $fields ) ; }
    unset ($fields, $mask, $pattern, $matches, $match);
     
    ?><pre><?php print_r( $result  ); ?></pre>
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  9. #9
    Membre régulier Avatar de PIEPLU
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    507
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 507
    Points : 92
    Points
    92
    Par défaut
    Merci pour tous vos codes, je n'ai que l’embarras du choix

    Comme l'avais vu leviathan516, c'est un log apache que je dois étudier.
    J'aimerais, à des fins persos, pouvoir analyser ce log.
    Le problème, c'est que chaque jour, le log fait près de 1 millions de lignes pour 230 Mo.

    Du coup, ça pose problème de "allowed memory".
    Apparemment, le fait d'avoir rajouté...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ini_set ('memory_limit', filesize ($chemin) + 4000000);
    ... permet de ne pas bloquer sur le file_get_contents. Par contre, ca plante sur l'explode.

    L'idée qui me venait donc, qui n'est pas forcément la meilleure, couper par paquet de lignes, mais je n'ai pas trouvé le bon logiciel

    Je suis preneur de toute idée

    Merci
    Vincent Pieplu
    Développeur Site Internet

  10. #10
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2004
    Messages : 108
    Points : 175
    Points
    175
    Par défaut
    En fait pour ce genre d’opération sur ce type de fichier je te conseillerais plus de te tourner directement vers un script perl . Ce langage est fait pour gérer les très gros fichier et plutôt adapter à ce que tu veux faire .

Discussions similaires

  1. [PHP 5.2] Explode et expression régulière
    Par renaud26 dans le forum Langage
    Réponses: 3
    Dernier message: 30/03/2011, 17h01
  2. [RegEx] explode, strstr, str.. utilise des expressions régulières ?
    Par newbie_php dans le forum Langage
    Réponses: 7
    Dernier message: 01/02/2010, 21h34
  3. [expression régulière] mon cerveau fait des noeuds..
    Par nawac dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 27/05/2003, 10h06
  4. Expressions réguliéres
    Par Tooms dans le forum Langage
    Réponses: 4
    Dernier message: 06/12/2002, 18h42
  5. Réponses: 5
    Dernier message: 11/06/2002, 15h21

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