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

C# Discussion :

C# et regex - Trouver une chaîne OU la fin d'un string


Sujet :

C#

  1. #1
    Membre à l'essai
    Profil pro
    Employé
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Employé

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 18
    Points
    18
    Par défaut C# et regex - Trouver une chaîne OU la fin d'un string
    Bonjour à tous,

    je voudrais utiliser les regex pour traiter les différents messages présents dans un fichier texte.
    Les messages commencent tous par la ligne Message RCV suivi d'une date.
    Exemple :
    Message RCV 2016/03/03 14:12:11
    La suite d'un message est constituée de plusieurs lignes pouvant contenir n'importe quoi (lettres, chiffres, caractères spéciaux).

    Je commence par rapatrier le contenu du fichier dans un string.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string fullMess = File.ReadAllText(filePath);
    Ensuite j'utilise le regex suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Match m;
    string reg = @"Message RCV(.+?)(?=Message RCV)";
    m = Regex.Match(fullMess, reg, RegexOptions.IgnoreCase | RegexOptions.Singleline);
    Ça fonctionne pas mal mais ça omet systématiquement le dernier message, vu que par définition il n'est pas suivit de Message RCV.
    Je voudrais donc modifier mon regex pour que la recherche s'arrête lorsqu'elle trouve Message RCV ou bien la fin du string.

    Quelqu'un aurait-il une idée ?

    Merci beaucoup.

  2. #2
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    Je le fairai comme ca

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    string fullMess = "Message RCV test1\r\nblablaMessage RCV test2\r\nMessage RCV test3";
    string reg = @"Message RCV(.+?)(?=Message RCV|$)";
    MatchCollection matches = Regex.Matches(fullMess, reg, RegexOptions.IgnoreCase | RegexOptions.Singleline);
    foreach (Match match in matches)
        Console.WriteLine(match.Value);

  3. #3
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    je voudrais utiliser les regex pour traiter les différents messages présents dans un fichier texte.
    ...
    Je commence par rapatrier le contenu du fichier dans un string.
    Pourquoi? Ce n'est pas forcément le bon réflexe. L'utilisation d'une regex ne doit pas servir de béquille pouvant dispenser d'un algorithme somme toute basique.

    D'entrée de jeu, en faisant ce choix arbitraire, tu t'imposes le coût d'une regex qui s'accompagne d'un coût de mémoire car avec cette approche tu dois charger l'intégralité du fichier. Alors bien sûr ça ne porte pas à conséquence si le fichier est petit et si les messages sont courts (pour ce dernier point, garde à l'esprit que .*?(?:Message RCV|$) devra tester à chaque position de la chaîne si elle est suivie de "Message RCV" ou de la fin de la chaîne. Le prix à payer pour ce quantificateur non-gourmand suivi d'une alternative dépendra donc de la longueur du message, ce qui peut ne pas être rien même pour un outil conçu pour ça).

    Ce que tu peux faire c'est lire ton fichier ligne par ligne, ce qui a l'avantage d'économiser de la mémoire et de solutionner ton problème en évitant la regex. Utilise indexOf(String) pour détecter la présence de "Message RCV" et ajoute les lignes de chaque message à un StringBuilder.

    Autre approche si le fichier est petit: charge le dans une String, mais cette fois ci, au lieu de chercher à matcher le message, split ta chaîne avec "Message RCV" et élimine le premier item du tableau résultant. De cette manière, tu éviteras le quantificateur non gourmand et la recherche sera bien plus rapide.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  4. #4
    Membre à l'essai
    Profil pro
    Employé
    Inscrit en
    Septembre 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Employé

    Informations forums :
    Inscription : Septembre 2007
    Messages : 19
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par CosmoKnacki Voir le message
    Pourquoi? Ce n'est pas forcément le bon réflexe. L'utilisation d'une regex ne doit pas servir de béquille pouvant dispenser d'un algorithme somme toute basique.

    D'entrée de jeu, en faisant ce choix arbitraire, tu t'imposes le coût d'une regex qui s'accompagne d'un coût de mémoire car avec cette approche tu dois charger l'intégralité du fichier. Alors bien sûr ça ne porte pas à conséquence si le fichier est petit et si les messages sont courts (pour ce dernier point, garde à l'esprit que .*?(?:Message RCV|$) devra tester à chaque position de la chaîne si elle est suivie de "Message RCV" ou de la fin de la chaîne. Le prix à payer pour ce quantificateur non-gourmand suivi d'une alternative dépendra donc de la longueur du message, ce qui peut ne pas être rien même pour un outil conçu pour ça).

    Ce que tu peux faire c'est lire ton fichier ligne par ligne, ce qui a l'avantage d'économiser de la mémoire et de solutionner ton problème en évitant la regex. Utilise indexOf(String) pour détecter la présence de "Message RCV" et ajoute les lignes de chaque message à un StringBuilder.

    Autre approche si le fichier est petit: charge le dans une String, mais cette fois ci, au lieu de chercher à matcher le message, split ta chaîne avec "Message RCV" et élimine le premier item du tableau résultant. De cette manière, tu éviteras le quantificateur non gourmand et la recherche sera bien plus rapide.
    Super! Grand merci pour les conseils.
    La raison pour laquelle je charge le fichier entier en mémoire est que celui-ci est mis à jour par un autre logiciel et j'ai constaté qu'un accès à ce fichier (même en lecture) faisait planter l'autre logiciel s'il voulait l'éditer en même temps. De toutes façons le fichier n'est pas très grand et je le vide après chaque analyse.
    Par contre, j'ai constaté comme tu le soulignes qu'utiliser les regex dans ce cas ralentissait fortement le processus. J'ai commencé mon programme en utilisant un string[] et en analysant chaque ligne pour voir si elle débutait un autre message. C'est une solution qui fonctionnait très bien.
    Mais après coup, j'ai pensé que les regex, conçus spécialement pour le "traitement de texte" seraient une solution plus rapide et plus fiable. Mais en ce qui concerne la rapidité je m'étais peut-être trompé. Je n'aurais pas cru que les regex ralentiraient tant cette partie de code et consommeraient tant de mémoire.
    Je vais tenter ton approche avec indexOf(String) et un StringBuilder. Ça a l'air encore mieux que ce que j'avais fais à l'origine.

    Merci aussi à ericlm128 pour ta solution, mais je l'avais déjà testée sans succès Si mes souvenirs sont bons d'ailleurs, je devais en fait stopper l'application car elle bloquait sur le regex. Comme l'a souligné CosmoKnacki, c'est une solution qui prend énormément de temps.

  5. #5
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    Ça fonctionne correctement chez moi cependant.

Discussions similaires

  1. [Regex] Récupérer une chaîne qui suit un caractère spécial
    Par dev197 dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 30/09/2009, 12h01
  2. trouver une chaîne dans un champ
    Par cycloop dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 24/07/2009, 14h36
  3. Regex: trouver une chaine et prendre le mot d'aprés
    Par Greg84 dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 07/11/2008, 14h41
  4. [Regex] reconnaitre une chaîne non complète
    Par EdoBvD dans le forum Collection et Stream
    Réponses: 19
    Dernier message: 13/07/2004, 17h14

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