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 Perl Discussion :

Question sur l'ordre du "match"


Sujet :

Langage Perl

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 195
    Points : 121
    Points
    121
    Par défaut Question sur l'ordre du "match"
    Bonjour,

    je viens avec une question générale et non un script à débugger.

    C'est concernant le "match", il peut arriver que l'on veuille "matcher" ce qui suit un symbole, nom.
    Mais si dans les lignes il y a plusieurs fois le caractère précéde le résultat recherché ?
    Y a t'il un moyen de "matcher" tel caractère à partir du 3è qui se présente par exemple.

    Sur internet j'avais trouvé cet exemple qui match après le signe "=" (même si dans ce cas les /g je ne comprend pas ce qu'ils font la mais sans ca ne marche pas)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    my $_ = 'b=var1+var2';
    # force further /g matches to start after the first '='
    /=/g;
     
    while (/(\w+)/g) {
        print "$1\n";
    }
    #Résultat
    var1
    var2


    Mais si par exemple on prend un fichier de log comme ci-dessous et l'on veut récupérer dans des variables tel ou tel valeur après tel ou tel signe ":" par exemple ?

    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of
    interface: fxp0.0Name of protocol: TCP, Packet Length: 50824, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 1020, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513

    J'ai été assez clair dans la question?

    merci pour l'éclairage à venir ou solution plus simple proposée.

  2. #2
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2013
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 247
    Points : 406
    Points
    406
    Par défaut
    avec des expressions régulières je pense que ça peut le faire du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while ( $_ =~ /^Time\s*of\s*Log\s*:(.*):(.*):(.*)$/ )
    si tu dis la(es) partie(s) que tu veux récupérer, on pourra plus t'aider

  3. #3
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    A partir de perl 5.10, tu peux utiliser les assertions postfix ou prefix, qui recherchent un motif suivant ou précédent un autre motif (avec la limitation que le motif à suivre ou précéder doit être de taille fixe).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my $request = "field1:toto; field2:titi";
    foreach my $field ($request =~ /(?<=:)(\w+)/g) {
      say $field;
    }
    donne
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  4. #4
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 276
    Points : 12 721
    Points
    12 721
    Par défaut
    On peut l'expression sous forme de pseudo-index, voici un exemple qui récupére tout depuis le niéme ':' jusqu'a la fin de la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    perl -n -e '/^([^:]*:){3}(.*)/ ; print $2."\n"' log
    En rouge, il suffit de changer le 3 par celui a partir duquel tu veux récupérer le reste de la ligne.
    Si ce n'est pas le reste de la ligne qui t'interresse, il suffit de modifier la partie bleue.
    Cordialement.

  5. #5
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par caramon _majere Voir le message
    Bonjour,

    je viens avec une question générale et non un script à débugger.

    C'est concernant le "match", il peut arriver que l'on veuille "matcher" ce qui suit un symbole, nom.
    Mais si dans les lignes il y a plusieurs fois le caractère précéde le résultat recherché ?
    Y a t'il un moyen de "matcher" tel caractère à partir du 3è qui se présente par exemple.

    Sur internet j'avais trouvé cet exemple qui match après le signe "=" (même si dans ce cas les /g je ne comprend pas ce qu'ils font la mais sans ca ne marche pas)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    my $_ = 'b=var1+var2';
    # force further /g matches to start after the first '='
    /=/g;
     
    while (/(\w+)/g) {
        print "$1\n";
    }
    #Résultat
    var1
    var2
    le suffix /g signifie 'global' et permet de faire plusieurs match successifs en progressant dans une même chaîne.

    Ici, le premier match (/=/g) démarre du début de la chaîne, et s'arrête quand il a trouvé un caractère '='. La position de départ pour les prochains matches appliqués sur cette chaîne avec le suffix /g sera celle du caractère suivant et est accessible par la fonction pos :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/tttmp $ perl -E '$str = q{foo = bar + qux}; $str =~ m/=/g; say pos($str)'
    5
    Taisha:~/tttmp $
    Cette fonction permet également de positionner explicitement le point de démarrage de la recherche dans la chaîne. En cas d'échec du match, la position est remise à '', sauf si on utilise le suffixe c, auquel cas elle contient la position du caractère suivant le dernier match
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Taisha:~/tttmp $ perl -E '$str = q{foo = bar + qux}; pos($str) = 5; @vars = $str =~ m/(\w+)/gc; say "@vars"; say q{pos est maintenant }, pos($str)'
    bar qux
    pos est maintenant 15
    Taisha:~/tttmp $
    Mais si par exemple on prend un fichier de log comme ci-dessous et l'on veut récupérer dans des variables tel ou tel valeur après tel ou tel signe ":" par exemple ?

    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of
    interface: fxp0.0Name of protocol: TCP, Packet Length: 50824, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 1020, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513

    J'ai été assez clair dans la question?

    merci pour l'éclairage à venir ou solution plus simple proposée.
    A vue de nez, ce que tu as ici ce sont des couples clé: valeur séparés par des ',', et c'est probablement comme ça qu'il faut prendre le problème. La clé ne semble pas pouvoir contenir ':', donc on peut utiliser split pour décomposer un couple, en utilisant le 3eme paramètre (limite) pour ne pas découper sur les ':' pouvant apparaître dans les valeurs (séparateur heure:minutes:secondes par exemple).

    Ce log est un peu pénible si les lignes forment en fait des groupes. Je considère que c'est le cas, et qu'un groupe commence par 'Time of Log'.

    Après correction triviale du log au début :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of 
    interface: fxp0.0Name of protocol: TCP, Packet Length: 50824, Source address: 172.17.22.108:829,
    en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 50824, Source address: 172.17.22.108:829,
    (comme les autres),
    le code ci-dessous
    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
    # -*- Mode: cperl; coding: utf-8; tab-width: 8; indent-tabs-mode: nil; cperl-indent-level: 4 -*-
    # parse1.pl
    use strict;
    use warnings;
    use Data::Dumper;
     
    my @entries;
    {
        local $/ = 'Time of Log';
        while (my $text = <DATA>) {
    	next if $text eq $/;
    	$text =~ s{$/$}{};
    	$text = $/ . $text;
    	$text =~ s/\n/,/sg;
    	my %pairs = map { split /:\s*/s, $_, 2 } split /\s*,\s*/s, $text;
    	push @entries, \%pairs;
        }
    }
    print Data::Dumper->Dump([\@entries], [qw(*entries)]);
     
    __DATA__
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 50824, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 1020, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    produit
    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    Taisha:~/tttmp/parselog $ perl parse1.pl
    @entries = (
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '50824'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '1020'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '49245'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '49245'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '49245'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '49245'
                 }
               );
    Taisha:~/tttmp/parselog $
    Sinon on peut bien sûr construire plutôt une structure hiérarchique mais ça ne semble pas nécessaire ici...
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  6. #6
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 195
    Points : 121
    Points
    121
    Par défaut
    Merci pour vos réponses

    J'ai une préférence pour les solutions de Philou67430 et disedorgue car elles évites trop de modifications si on tombe sur un autre format.

    Sur la solution de Philou, tous les résultat sont affichés car tous le même nom de variable. Ains il n'y a pas de différence pour faire un choix du résultat à affiché.
    Un peu comme dans la ligne CLI de disedorgue.

    J'essaye de faire un mixte des deux pour arriver au résultat final

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $request = "field1:toto; field2:titi";
    say $1 if $request =~ /^([^:]*:){2}(\w+)/ ;
    Résultat
    toto sans la suite, c'est bon

    Par contre si je veux capturer deux valeur ? (ici titi et tata que j'ai rajouté)


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $request = "field1:toto; field2:titi; field3:tata";
    say $2  $3 if $request =~ /^([^:]*:){2}(\w+){3}(\w+)/ ;
    Résultat ...pas terrible
    t i

    J'ai essayé de le faire en deux fois mais idem

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my $request = "field1:toto; field2:titi; field3:tata";
    my $var1 = $request =~ /^([^:]*:){2}(\w+)/;
    my $var2 = $request =~ /^([^:]*:){3}(\w+)/;
    say "$var1\t$var2";
    Résultat
    1 1

  7. #7
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 195
    Points : 121
    Points
    121
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    le suffix /g signifie 'global' et permet de faire plusieurs match successifs en progressant dans une même chaîne.

    Ici, le premier match (/=/g) démarre du début de la chaîne, et s'arrête quand il a trouvé un caractère '='. La position de départ pour les prochains matches appliqués sur cette chaîne avec le suffix /g sera celle du caractère suivant et est accessible par la fonction pos :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/tttmp $ perl -E '$str = q{foo = bar + qux}; $str =~ m/=/g; say pos($str)'
    5
    Taisha:~/tttmp $
    Cette fonction permet également de positionner explicitement le point de démarrage de la recherche dans la chaîne. En cas d'échec du match, la position est remise à '', sauf si on utilise le suffixe c, auquel cas elle contient la position du caractère suivant le dernier match
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Taisha:~/tttmp $ perl -E '$str = q{foo = bar + qux}; pos($str) = 5; @vars = $str =~ m/(\w+)/gc; say "@vars"; say q{pos est maintenant }, pos($str)'
    bar qux
    pos est maintenant 15
    Taisha:~/tttmp $


    A vue de nez, ce que tu as ici ce sont des couples clé: valeur séparés par des ',', et c'est probablement comme ça qu'il faut prendre le problème. La clé ne semble pas pouvoir contenir ':', donc on peut utiliser split pour décomposer un couple, en utilisant le 3eme paramètre (limite) pour ne pas découper sur les ':' pouvant apparaître dans les valeurs (séparateur heure:minutes:secondes par exemple).

    Ce log est un peu pénible si les lignes forment en fait des groupes. Je considère que c'est le cas, et qu'un groupe commence par 'Time of Log'.

    Après correction triviale du log au début :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of 
    interface: fxp0.0Name of protocol: TCP, Packet Length: 50824, Source address: 172.17.22.108:829,
    en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 50824, Source address: 172.17.22.108:829,
    (comme les autres),
    le code ci-dessous
    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
    # -*- Mode: cperl; coding: utf-8; tab-width: 8; indent-tabs-mode: nil; cperl-indent-level: 4 -*-
    # parse1.pl
    use strict;
    use warnings;
    use Data::Dumper;
     
    my @entries;
    {
        local $/ = 'Time of Log';
        while (my $text = <DATA>) {
    	next if $text eq $/;
    	$text =~ s{$/$}{};
    	$text = $/ . $text;
    	$text =~ s/\n/,/sg;
    	my %pairs = map { split /:\s*/s, $_, 2 } split /\s*,\s*/s, $text;
    	push @entries, \%pairs;
        }
    }
    print Data::Dumper->Dump([\@entries], [qw(*entries)]);
     
    __DATA__
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 50824, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 1020, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    Time of Log: 2004-10-13 10:37:17 PDT, Filter: f, Filter action: accept, Name of interface: fxp0.0
    Name of protocol: TCP, Packet Length: 49245, Source address: 172.17.22.108:829,
    Destination address: 192.168.70.66:513
    produit
    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    Taisha:~/tttmp/parselog $ perl parse1.pl
    @entries = (
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '50824'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '1020'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '49245'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '49245'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '49245'
                 },
                 {
                   'Name of protocol' => 'TCP',
                   'Name of interface' => 'fxp0.0',
                   'Time of Log' => '2004-10-13 10:37:17 PDT',
                   'Filter' => 'f',
                   'Filter action' => 'accept',
                   'Source address' => '172.17.22.108:829',
                   'Destination address' => '192.168.70.66:513',
                   'Packet Length' => '49245'
                 }
               );
    Taisha:~/tttmp/parselog $
    Sinon on peut bien sûr construire plutôt une structure hiérarchique mais ça ne semble pas nécessaire ici...

    ouch, je vois l'idée mais étant un newbie en perl, je comptais passer du temps sur le mécanisme des expression régulières plus haut mais la j'ai mal au crâne sans alcool

    Ca fera de quoi étudier

    Je n'avais pas vu ta réponse et avait répondu avant sur les réponses précédentes ...Mes résultats étaient plus modestes

  8. #8
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par caramon _majere Voir le message
    J'ai une préférence pour les solutions de Philou67430 et disedorgue car elles évites trop de modifications si on tombe sur un autre format.
    ? [EDIT : ok, je n'avais pas vu ton message de 15:43 ]

    ...J'ai essayé de le faire en deux fois mais idem...
    c'est à ça que sert /g...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Taisha:~/tttmp/parselog $ perl -E 'my $request = q{field1:toto; field2:titi; field3:tata}; say "$1 => $2" while $request =~ /([^:;]+):\s*([^;]+);?\s*/g'
    field1 => toto
    field2 => titi
    field3 => tata
    Taisha:~/tttmp/parselog $
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  9. #9
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Pour reprendre ce que j'avais écrit, et récupérer le 3 éléments suivant ":", tu peux écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    my $request = "field1:toto; field2:titi; field3:tata";
    say [$request =~ /(?<=:)(\w+)/g]->[2];
    Si tu veux récupérer à la fois ce qui est avant le ":" et ce qui est après, tu peux simplement écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $request = "field1:toto; field2:titi; field3:tata";
    say [$request =~ /(\w+:\w+)/g]->[2];
    ou bien travailler avec des split, ou bien encore écrire comme dans le message précédent de cmcmc.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  10. #10
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    c'est à ça que sert /g...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Taisha:~/tttmp/parselog $ perl -E 'my $request = q{field1:toto; field2:titi; field3:tata}; say "$1 => $2" while $request =~ /([^:;]+):\s*([^;]+);?\s*/g'
    field1 => toto
    field2 => titi
    field3 => tata
    Taisha:~/tttmp/parselog $
    une version plus safe, qui sort en erreur si on n'a pas analysé l'intégralité de la ligne (note les ancrages au début par \G et en fin par $)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Taisha:~/tttmp/parselog $ perl -E 'my $request = q{field1:toto; field2:titi; field3:tata}; say "$1 => $2" while $request =~ /\G([^:;]+):\s*([^;]+)(?:(?:;\s*)|(?:\s*$))/gc; die q{echec en position }, pos($request), q{ à partir de [}, substr($request, pos($request), 10), q{]} if pos($request) < length($request)'
    field1 => toto
    field2 => titi
    field3 => tata
    Taisha:~/tttmp/parselog $ perl -E 'my $request = q{field1:toto; field2:titi; field3:tata; blearch}; say "$1 => $2" while $request =~ /\G([^:;]+):\s*([^;]+)(?:(?:;\s*)|(?:\s*$))/gc; die q{echec en position }, pos($request), q{ à partir de [}, substr($request, pos($request), 10), q{]} if pos($request) < length($request)'
    echec en position 39 à partir de [blearch] at -e line 1.
    field1 => toto
    field2 => titi
    field3 => tata
    Taisha:~/tttmp/parselog $
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  11. #11
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $request = "field1:toto; field2:titi; field3:tata";
    say [$request =~ /(\w+:\w+)/g]->[2];
    Amateurs de copies surnuméraires, bonjour

    Pour les autres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/tttmp/parselog $ perl -E 'my $request = "field1:toto; field2:titi; field3:tata"; say +($request =~ /(\w+:\w+)/g)[2];'
    field3:tata
    Taisha:~/tttmp/parselog $
    Ok, je sors
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  12. #12
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 195
    Points : 121
    Points
    121
    Par défaut
    Bah en fait en utilisant ceci tu as pile les mots recherché

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my $request = "field1:toto; field2:titi; field3:tata";
    my $var1 = [$request =~ /(?<=:)(\w+)/g]->[1];
    my $var2 = [$request =~ /(?<=:)(\w+)/g]->[2];
    say "$var1\t$var2";
    Résultats
    titi tata

    Les valeurs pourront être traités plus facilement à part comme ca.

    Mais le coup de la CLI est à garder dans un coin de la tête

    Merci à vous pour cette masse d'informations...un digestif s'impose la

  13. #13
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    Amateurs de copies surnuméraires, bonjour
    Merci pour la syntaxe correcte, que je n'avais pas retrouvée.
    Tu peux développer le concept (ici ou en MP, vu que c'est hors sujet).
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  14. #14
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    Merci pour la syntaxe correcte, que je n'avais pas retrouvée.
    Tu peux développer le concept (ici ou en MP, vu que c'est hors sujet).
    Okidoki . Si expression s'évalue à une liste, on peut accéder directement au n ème élément (en partant de 0) par (expression)[n]. On peut y accéder également par [expression]->[n] mais cette seconde forme effectue une copie, du résultat (anonyme) de l'évaluation de expression dans une autre liste anonyme, celle construite par [ ... ]. Autant éviter cette copie inutile.


    Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/tttmp $ perl -E 'say q{la seconde valeur est }, (split /:/, q{a:b:c})[1]'
    la seconde valeur est b
    Taisha:~/tttmp $
    Mais pourtant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Taisha:~/tttmp $ perl -E 'say (split /:/, q{a:b:c})[1]'
    syntax error at -e line 1, near ")["
    Execution of -e aborted due to compilation errors.
    Taisha:~/tttmp $
    Qu'est-ce qui se passe ? Tout ce qu'on a fait c'est enlever la chaîne d'entête... En fait l'interpréteur perl considère ici qu'on a un appel parenthésé "say(...)" suivi de "[1]", une construction syntaxiquement incorrecte (cette interprétation n'était pas possible lorsque la chaîne d'entête était présente). Pour lever l'ambiguïté on peut utiliser un signe + qui va indiquer que ce qui suit est une expression.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/tttmp $ perl -E 'say +(split /:/, q{a:b:c})[1]'
    b
    Taisha:~/tttmp $
    De manière analogue, ce caractère permet de lever certaines ambiguïtés apparaissant lorsqu'une paire {...} pourrait signifier aussi bien un bloc imbriqué que le constructeur de hash anonyme. Ainsi le + ci-dessous force l'interprétation 'hash'
    On peut à l'inverse forcer l'interprétation 'bloc' comme suit
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  15. #15
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 276
    Points : 12 721
    Points
    12 721
    Par défaut
    Juste pour la version pseudo index sur la regex elle-même, soit tu utilises la même syntaxe que Philou67430:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my $request = "field1:toto; field2:titi; field3:tata";
    my $var1 = [$request =~ /([^:]*:){2}(\w+)/]->[1];
    my $var2 = [$request =~ /([^:]*:){3}(\w+)/]->[1];
    print $var1."\t".$var2."\n";
    Soit tu utilises la syntaxe suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my $request = "field1:toto; field2:titi; field3:tata";
    $request =~ /([^:]*:){2}(\w+)/;
    my $var1 = $2;
    $request =~ /([^:]*:){3}(\w+)/;
    my $var2 = $2;
    print $var1."\t".$var2."\n";
    En rouge, ce qui change selon le champs.
    Cordialement.

  16. #16
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 195
    Points : 121
    Points
    121
    Par défaut
    Je vais rester sur la première version ...parce que vu mon niveau de débutant la construction est plus "logique" ....mais c'est ce n'est que mon point de vue

    Je ne pensais pas avec cette question avoir autant de matières en retour à étudier

  17. #17
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    Bien que cette syntaxe soit parfaitement correcte, claire à les yeux et admissible (en particulier pour un script uniligne), je préfère, dans un vrai programme, utiliser des parenthèses supplémentaires explicitant à mon avis clairement l'objectif à l'intention du développeur qui devra maintenir mon code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     perl -E 'say ((split /:/, q{a:b:c})[1])'
    ou utiliser une variable intermédiaire (ce qui est bien sûr excessif dans un uniligne, mais justifié à mes yeux dans un vrai programme):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     perl -E '$c= (split /:/, q{a:b:c})[1]; print $c'
    Quant à l'interprétation "bloc"

    elle est certes une solution, mais je viens il y a quelques jours de passer une bonne demi-heure à trouver le moyen de l'éviter (moyennant l'utilisation d'un prototype pour ma fonction), parce que je ne voulais surtout pas imposer ce genre de syntaxe plus compliquée à l'utilisateur de mon module.

  18. #18
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    On peut y accéder également par [expression]->[n] mais cette seconde forme effectue une copie, du résultat (anonyme) de l'évaluation de expression dans une autre liste anonyme, celle construite par [ ... ]. Autant éviter cette copie inutile.
    Cette explication m'était suffisante... c'était juste pour confirmer que j'avais bien compris, et que le terme "copies surnuméraires" ne cachait pas autre chose.
    En fait l'interpréteur perl considère ici qu'on a un appel parenthésé "say(...)" suivi de "[1]", une construction syntaxiquement incorrecte (cette interprétation n'était pas possible lorsque la chaîne d'entête était présente).
    Merci pour les explications, et celles de Lolo sur le même sujet.
    J'utiliserai +(...)[...] dorénavant (j'avais bien remarqué que (...)[...] marchait dans certains contextes et pas dans d'autres, sans avoir trouvé l'explication du say ()).
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Petite question sur l'ordre des déclarations en python.
    Par vmonteco dans le forum Général Python
    Réponses: 6
    Dernier message: 05/09/2014, 11h16

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