2010-08-29 20 views
1

J'utilise tr1 :: regex pour essayer d'extraire des correspondances d'une chaîne. Une chaîne exemple pourrait êtretr1 :: regex regex_search problème

asdf werq "one two three" asdf 

Et je veux sortir de cette:

asdf 
werq 
one two three 
asdf 

avec des choses entre guillemets regroupées, donc je suis en train d'utiliser l'expression rationnelle \"(.+?)\"|([^\\s]+). Le code J'utilise est:

cmatch res; 
regex reg("\"(.+?)\"|([^\\s]+)", regex_constants::icase); 
regex_search("asdf werq \"one two three\" asdf", res, reg); 

cout << res.size() << endl; 
for (unsigned int i = 0; i < res.size(); ++k) { 
    cout << res[i] << endl; 
} 

mais qui sort

3 
asdf 

asdf 

Qu'est-ce que je fais mal?

Répondre

0

Il semble que votre moteur regex ne supporte pas les assertions lookbehind. Pour éviter d'utiliser assertions arrières, vous pouvez essayer ce qui suit:

"([^"]*)"|(\S+) 

ou cité:

"\"([^\"]*)\"|(\\S+)" 

Cette regex fonctionnera, mais chaque match aurez deux captures, dont un sera vide (soit la d'abord - dans le cas d'un mot non cité, ou le second - dans le cas d'une chaîne entre guillemets). Pour pouvoir utiliser ceci, vous devez parcourir toutes les correspondances et pour chaque correspondance utiliser la capture non vide. Je ne connais pas assez TR1, donc je ne sais pas exactement comment on itère sur toutes les correspondances. Mais si je ne me trompe pas, le res.size() sera toujours égal à 3.

Par exemple, pour la chaîne asdf "one two three" werq le premier match sera:

res[0] = "asdf"    // the entire match 
res[1] = ""     // the first capture 
res[2] = "asdf"    // the second capture 

Le deuxième match sera:

res[0] = "\"one two three\"" // the entire match including leading/trailing quotes 
res[1] = "one two three"  // the first capture 
res[2] = ""     // the second capture 

et le troisième match sera:

res[0] = "werq"    // the entire match 
res[1] = ""     // the first capture 
res[2] = "werq"    // the second capture 

HTH.

+0

Comment puis-je obtenir la correspondance comme vous l'avez dit si j'utilise un itérateur? Vous utilisez un itérateur dans le style de (std :: tr1 :: sregex_token_iterator je (str.begin(), str.end(), reg); i! = fin; ++ i) {cout << * i;} Vous n'avez pas vraiment le choix de savoir si vous obtenir la correspondance complète, première capture ou seconde capture, que je peux voir –

+0

Qu'en est-il de ce qui suit: 'for (std :: tr1 :: sregex_token_iterator je (str.begin(), str.end(), reg); ! = fin; ++ i) {cout << ((* i) [1] || (* i) [2]);} '? Je ne peux pas vérifier si cela compile, et encore moins s'il fonctionne, mais l'idée est que '* i' est un objet qui a un opérateur d'indexation, ce qui devrait vous donner les captures. –

0

Vous pouvez essayer la place regex suivante:

(?<=")[^"]*(?=")|[^"\s]\S* 

Quand cité, il bien sûr doit être échappé:

"(?<=\")[^\"]*(?=\")|[^\"\\s]\\S*" 

BTW, le code utilisé correspond probablement la première mot dans la chaîne cible, car il n'utilise pas match_any. Les 3 éléments que vous obtenez dans le résultat sont probablement (1) le match entier, (2) la première capture - qui est vide, et (3) la deuxième capture, qui est la source du match.

+0

En fait quand j'utilise cette regex, quand j'exécute le programme, ceci est sorti sur la console: "Cette application a demandé au Runtime de le terminer de façon inhabituelle. ..." bla bla bla, et il des accidents. –

+0

Je ne dispose pas d'un environnement de travail dans lequel je peux vérifier cela, mais j'ai testé l'expression régulière avec Java et C#, et il ne s'est pas crashé non plus. Veuillez utiliser syntax_option_type = extended pour vous assurer qu'il respecte la syntaxe standard pour les regexes étendues. (BTW, j'ai fait une petite correction à la première partie de l'expression rationnelle pour l'empêcher de capturer un espace après la fin d'un mot cité.) –

+0

Vous êtes invités à jouer avec la regex ici: http: // www .myregextester.com /? r = a9e366fd –