Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

GENERATION DE L'EXPRESSION REGULIERE (REGEXP) POUR MANGER JUSQU'A UNE CHAINE


Information sur la source

Catégorie :Astuces Classé sous : expression, régulière, regular, generation, tag Niveau : Initié Date de création : 04/11/2007 Date de mise à jour : 04/11/2007 12:16:56 Vu : 4 271

Note :
Aucune note

Commentaire sur cette source (1)
Ajouter un commentaire et/ou une note


Description

Bon je sais pas vous mais moi ça me gonfle de devoir écrire l'expression reguliere qui signifie : "manger jusqu'a" !

Exemple :
1) Vous souhaitez chercher une balise html
   <truc ... >
   Facile ! C'est "<[^>]*>"

2) Vous souhaitez chercher un commentaire en c++, php, ...
   /* commentaire [sur plusieurs lignes] */
   Heu attend je réfléchi ... arf galère

3) Vous souhaitez chercher des commentaires html
   <!-- ... -->
  Heu attend .. AU SECOUR !!!


Bon clairement ca devient vite infernal !
Donc le but de cette source est de générer la regexp qui va manger tout jusqu'à une chaine précise (la chaine est inclue dans le repas de la regexp :p)
Les expressions régulières requise pour les exemples ci-dessus s'écriront donc :
1) "<" + UNTIL_WITH(">");
2) "/\*" + UNTIL_WITH("*/");
2) "<!--" + UNTIL_WITH("-->");

Carrément plus simple non ? :)
Le code est un peu astucieux et faut réfléchir pour le comprendre ...
Bon je sais ... vous allez tous pomper le code et basta X-D !

La fonction UNTIL_WITH prend en argument une chaine normale,
les caractères spéciaux n'ont pas besoin d'être échappé.
Une variable static recense les caracteres qui seront echappé automatiquement.

Les autres variables static sont à modifier par vos soins !
(super rapide normalement si vous connaissez les regexp)

J'ai fait une autre fonction UNTILS_WITH (notez le 'S' à UNTIL) qui génère une regexp qui mange tout jusqu'à tomber sur une des deux chaines.
Exemple : UNTILS_WITH("fin", "end");
La fonction est EXTREMEMENT simple car elle utilise juste UNTIL_WITH !
En regardant la source vous pourrez faire une liste aussi longue que vous le souhaitez.

A noter enfin qu'au cas ou une chaine est prefixe d'une autre cela ne pose pas de probleme,
c'est la chaine la plus longue qui sera manger à la fin.

 

Source

  • #include <string>
  • #include <iostream>
  • using namespace std;
  • static const string to_escape = "^\\*+()[]{}$"; // Tous les caracteres qui ont besoin d'etre echapp?
  • static const char escape_char = '\\';
  • static const string parent_open = "(?:"; // Parenthese ouvrante non capturante pour ne pas gener les matchs, (en general "(?:")
  • static const char parent_close = ')';
  • static const char bracket_open = '[';
  • static const char bracket_close = ']'; // A placer au debut de classe d'intervalle
  • static const char bracket_not = '^'; // Parfois egal a '!'
  • typedef string (*func)(const string& word, int length);
  • // Echappe simplement les caracteres
  • // Contrainte : length >= 1 && word.length >= length
  • static string ESCAPE(const string& word, int length)
  • {
  • string res;
  • for (int i = 0; i < length; ++i)
  • {
  • if (string::npos != to_escape.find(word[i]))
  • res += escape_char;
  • res += word[i];
  • }
  • return res;
  • }
  • // Appelle ESCAPE
  • // ET ajoute une subtilit?
  • // Contrainte : <les memes que ESCAPE>
  • static string WITH(const string& word, int length)
  • {
  • string res = ESCAPE(word, length);
  • return res.insert(1 + (res[0] == escape_char), 1, '+'); // LA petite subtilit? :)
  • }
  • // Permet de construire une regexp qui mange tout et s'arrete apres une chaine donn?e
  • // Exemple pour matcher un commentaire en c++ : "/*" + UNTIL("*/") + "*/"
  • // Facile non ?
  • static string UNTIL_WITH(const string& word)
  • {
  • unsigned int n = word.length();
  • string res = n > 1 ? parent_open : "";
  • unsigned int i = 1;
  • while (i < word.length() && word[0] == word[i])
  • ++i;
  • func Subtility = i < word.length() ? WITH : ESCAPE;
  • // Optionnel, il s'agit d'un pronostic sur la taille probable
  • // Ce pronostic optimise un peu ...
  • // Le pronostic est inferieur ? la taille r?elle si des caract?res doivent etre echapp? !
  • // Comptons les caracteres ( n == word.length() )
  • // 1 : parenthese ouvrante
  • // n - 1 : Nombre de '|'
  • // n * 3 : Nombre de '[^]'
  • // n * 2 - 1 : Nombre de caracteres dans les crochets
  • // (n-1) * n / 2 + n -1 : Nombre de caracteres en dehors des crochets (somme de 0 a n - 1) et n-1 fois le '+'
  • // 1 + 1 : parenthese fermante et etoile
  • // n + 1 : Mot a manger a la fin avec le '+'
  • // Soit au final :
  • // {
  • res.reserve((15 + n) * n / 2 + 1);
  • // Version ou le pronostic >= taille reelle (considere que tous les caracteres ont besoin d'etre echapp?s) !
  • // res.reserve((n + 9) * n);
  • // }
  • for (i = 0; i < n; ++i)
  • {
  • if (i)
  • {
  • res += '|';
  • res += Subtility(word, i);
  • }
  • res += bracket_open;
  • res += bracket_not;
  • if (word[0] == word[i])
  • res += word[i];
  • else if (word[i] == bracket_close)
  • {
  • res += word[i];
  • res += word[0];
  • }
  • else
  • {
  • res += word[0];
  • res += word[i];
  • }
  • res += bracket_close;
  • }
  • if (n > 1)
  • res += parent_close;
  • res += '*' + Subtility(word, i);
  • return res;
  • }
  • // M?me chose que UNTIL mais pour s'arreter apres la premiere des deux chaines trouv?e
  • // Cette fonction est la fonction de base permetant de construire des listes de chaines devant lesquelles s'arreter.
  • // ( Certes UNTIL avec S n'existe pas mais tant pis :p )
  • static string UNTILS_WITH(const string& word_1, const string& word_2)
  • {
  • return parent_open + UNTIL_WITH(word_1) + "|" + UNTIL_WITH(word_2) + parent_close;
  • }
  • int main()
  • {
  • cout << "Commentaire C++, php ... :" << endl;
  • =>cout << "/\\*" + UNTIL_WITH("*/") << endl;
  • cout << endl;
  • cout << endl;
  • // Matcher un commentaire HTML selon la norme W3C
  • // format : <!-- blablabla -- blablabla >
  • // Et oui ! normalement -- et > ne sont pas forcement coll? :
  • cout << "Commentaire HTML (selon la norme W3C) :" << endl;
  • cout << "<!--" + UNTIL_WITH("--") + UNTIL_WITH(">") << endl;
  • cout << endl;
  • cout << endl;
  • cout << "jusqu'a \"abc\" :" << endl;
  • cout << UNTIL_WITH("abc") << endl;
  • cout << endl;
  • cout << endl;
  • return EXIT_SUCCESS;
  • }
#include <string>
#include <iostream>

using namespace std;

static const string to_escape   = "^\\*+()[]{}$"; // Tous les caracteres qui ont besoin d'etre echapp?
static const char   escape_char = '\\';
static const string parent_open   = "(?:"; // Parenthese ouvrante non capturante pour ne pas gener les matchs, (en general "(?:")
static const char   parent_close  = ')';
static const char   bracket_open  = '[';
static const char   bracket_close = ']'; // A placer au debut de classe d'intervalle
static const char   bracket_not   = '^'; // Parfois egal a '!'

typedef string (*func)(const string& word, int length);

// Echappe simplement les caracteres
// Contrainte : length >= 1 && word.length >= length

static string ESCAPE(const string& word, int length)
{
  string res;

  for (int i = 0; i < length; ++i)
  {
    if (string::npos != to_escape.find(word[i]))
      res += escape_char;
    res += word[i];
  }
  return res;
}

// Appelle ESCAPE
// ET ajoute une subtilit?
// Contrainte : <les memes que ESCAPE>
static string WITH(const string& word, int length)
{
  string res = ESCAPE(word, length);
  return res.insert(1 + (res[0] == escape_char), 1, '+'); // LA petite subtilit? :)
}

// Permet de construire une regexp qui mange tout et s'arrete apres une chaine donn?e
// Exemple pour matcher un commentaire en c++ : "/*" + UNTIL("*/") + "*/"
// Facile non ?
static string UNTIL_WITH(const string& word)
{
  unsigned int n = word.length();
  string res = n > 1 ? parent_open : "";
  unsigned int i = 1;

  while (i < word.length() && word[0] == word[i])
      ++i;
  func Subtility = i < word.length() ? WITH : ESCAPE;

  // Optionnel, il s'agit d'un pronostic sur la taille probable
  // Ce pronostic optimise un peu ...
  // Le pronostic est inferieur ? la taille r?elle si des caract?res doivent etre echapp? !
  // Comptons les caracteres ( n == word.length() )
  // 1 : parenthese ouvrante
  // n - 1 : Nombre de '|'
  // n * 3 : Nombre de '[^]'
  // n * 2 - 1 : Nombre de caracteres dans les crochets
  // (n-1) * n / 2 + n -1 : Nombre de caracteres en dehors des crochets (somme de 0 a n - 1) et n-1 fois le '+'
  // 1 + 1 : parenthese fermante et etoile
  // n + 1 : Mot a manger a la fin avec le '+'
  // Soit au final :
  // {
   res.reserve((15 + n) * n / 2 + 1);
  // Version ou le pronostic >= taille reelle (considere que tous les caracteres ont besoin d'etre echapp?s) !
  // res.reserve((n + 9) * n);
  // }

  for (i = 0; i < n; ++i)
  {
    if (i)
    {
      res += '|';
      res += Subtility(word, i);
    }
    res += bracket_open;
    res += bracket_not;
    if (word[0] == word[i])
      res += word[i];
    else if (word[i] == bracket_close)
    {
      res += word[i];
      res += word[0];
    }
    else
    {
      res += word[0];
      res += word[i];
    }
    res += bracket_close;
  }
  if (n > 1)
    res += parent_close;
  res += '*' + Subtility(word, i);
  return res;
}

// M?me chose que UNTIL mais pour s'arreter apres la premiere des deux chaines trouv?e
// Cette fonction est la fonction de base permetant de construire des listes de chaines devant lesquelles s'arreter.
// ( Certes UNTIL avec S n'existe pas mais tant pis :p )
static string UNTILS_WITH(const string& word_1, const string& word_2)
{
  return parent_open + UNTIL_WITH(word_1) + "|" + UNTIL_WITH(word_2) + parent_close;
}






int main()
{
  cout << "Commentaire C++, php ... :" << endl;
=>cout << "/\\*" + UNTIL_WITH("*/") << endl;
  cout << endl;
  cout << endl;

  // Matcher un commentaire HTML selon la norme W3C
  // format : <!-- blablabla -- blablabla >
  // Et oui ! normalement -- et > ne sont pas forcement coll? :
  cout << "Commentaire HTML (selon la norme W3C) :" << endl;
  cout << "<!--" + UNTIL_WITH("--") + UNTIL_WITH(">") << endl;
  cout << endl;
  cout << endl;

  cout << "jusqu'a \"abc\" :" << endl;
  cout << UNTIL_WITH("abc") << endl;
  cout << endl;
  cout << endl;

  return EXIT_SUCCESS;
}

Conclusion

Si y'a des bug hésitez pas !
J'ai pas super testé la fonction UNTIL_WITH.
Juste dans ma tête et dans le main ...

La source est dans la catégorie "Astuce" et non pas "Chaine de caractère" ...
Ai-je bien fait ?
 

Historique

04 novembre 2007 12:12:44 :
Retour en arriere apres prévisualisation. Je modifie un peu le texte et au moment de refaire la prévisualisation on me somme de mettre une explication sur la modif que j'ai faite... Faut-il envoyer un dictionnaire aux administrateurs pour Noël ? :-p
04 novembre 2007 12:16:56 :
Retour en arriere apres prévisualisation. Je modifie un peu le texte et au moment de refaire la prévisualisation on me somme de mettre une explication sur la modif que j'ai faite... Faut-il envoyer un dictionnaire aux administrateurs pour Noël ? :-p

Commentaires et avis

signaler à un administrateur
Commentaire de Zeroc00l le 22/12/2007 18:18:36

Pas mal de visiteurs, pas de message !
:'(

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

expression régulière C [ par Digaboy ] BonjourJe souhaiterais faire des expressions régulières en C. J'ai appris les bases grâce à ce tutorielPar contre je n'arrive pas à compiler mon code Expression régulières [ par poiuytrez3 ] Bonjour,j'essaye de détecter une date au format DD/MM/YYYY grave à une expression régulière que j'ai toruvé ici :http://www.regular-expressions.info/r Expression régulière POSIX abondante [ par sebclick ] Bonjour,Je cherche à traiter un fichier XML par un programme C à l'aide d'expression régulière pour récupérer le texte contenu entre deux balises.Voic besoin d'aide pour une expression régulière [ par psgkiki ] Bonjour a tous, Je suis entrain de faire un lex et un yacc et je cale sur une expression régulière. Je veux qu'il me renvoi le mot clé IDF à chaque fo filtrer un string avec une regular expression [ par olivierroyo ] Bonjour je souhaiterai filtrer un string et enlever les caracteres non autorisés.Pour cela ma regle de triage est definie par une expression du style Erreur de compilation(generation) [ par Dariush ] DariushBonjour tout le monde;J'ai téléchargé le visual C++ 2008 Expresse (sous vista).Lorsque je compile mon programmme , j'ai le message suivant:<fon l'algorithme aprori de generation des itemes frequents [ par arab10 ] salut, je cherche le code source de l'algorithme apriori, si quelqu'un peut m'aidre je serai tres reconnaissant.merci d'avance. Problème de comprehension de programme... [ par Fathilde ] Bonjour à tous,Dans le cadre de mon stage je dois faire un programme en C++ (à l'aide de Borland C++) pour identifier des tags RFID, j'utilise pour ce conversion double en char* [ par snakers07 ] bonjour, voici mon probleme void grilleSetText(ligne,colonne,char*Text;) est une fonction comme ont peut le voir qui pren en parametre char*or j'ai un Aide sur la fonction OleFunction [ par volgin2 ] salut je cherche a remplir des formulaires automatiquement en utilisant Olefunctionje sais que pour reconnaitre un tag HTML grâce a la propriété "name


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,780 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.