2010-12-15 67 views
1

J'ai un peu de connaissances Regex, mais je suis perplexe par celui-ci. J'ai besoin d'un Regex qui correspond à tout avant le dernier trait de soulignement, mais seulement si le texte après le trait de soulignement est "self", "allié" ou "ennemi".Regex qui correspond à tout avant un trait de soulignement

Donc, si j'ai des chaînes d'entrée comme celui-ci:

"hero_anti_infantry_melee_2_self" 
"anti_infantry_ranged_2_ally" 
"suppression_aoe_enemy" 
"reinforce_btn_down" 
"inset_energy" 
"suppressed" 

je les veux à la sortie comme:

"hero_anti_infantry_melee_2" 
"anti_infantry_ranged_2" 
"suppression_aoe" 
//No Match (not match because it isn't enemy, ally, or self after the underscore) 
//No Match 
//No Match (not underscores or enemy/ally/self 

est d'utiliser le moteur C# Regex, et il peut utiliser toutes les options Regex nécessaires . Je vais donner une réponse acceptée et un upvote si cela fonctionne.

Modifier: Titre mis à jour.

Édition 2: Exemples fixes.

Répondre

5

Ce que vous voulez est un lookahead. Quelque chose comme cela devrait fonctionner:

new Regex(@"^.*(?=_(ally|self|enemy)$)") 

Le (?= ... ) signifie pretty much what you wanted:

zéro largeur avant positive. Correspond à une position où le motif à l'intérieur du lookahead peut être apparié. Correspond uniquement à la position. Il ne consomme aucun caractère ou ne développe pas le match. Dans un modèle comme un (? = Deux) trois, les deux et trois doivent correspondre à la position où la correspondance de l'un se termine.

modifier: MSDN a better examples pour cela.

+0

J'ai aussi réalisé que j'avais donné les mauvais exemples. Je ne suis pas sûr si cela affecte ou pas, puisque ce Regex ne semble pas fonctionner. – Miguel

+0

J'avais une faute de frappe dans la regex - ') $' au lieu de '$)'. Je l'ai également changé en syntaxe C# - et effectivement vérifié cela fonctionne cette fois. – configurator

+0

Fonctionne parfaitement. Et je pense que l'utilisation d'un lookahead est la plus logique.+1 – Miguel

1

/(.+)_(ally|self|enemy)/

+0

Je l'ai testé, et il semble que le modèle comprend l'ennemi \ allié \ auto après le trait de soulignement. Je préférerais qu'il corresponde au dernier trait de soulignement, mais seulement si les lettres qui suivent sont ennemies \ ally \ self (voir les 3 premiers exemples). Aussi, à quoi servent les barres obliques avant et après? – Miguel

+0

C'est la syntaxe php/perl, vous ne voulez examiner que la première capture de la correspondance pour vos besoins. (. + _) (allié | self | ennemi) –

1

Cette méthode vous donnera le résultat souhaité. Cela utilise le groupe nommé regex match.

private static string GetStringBeforeUnderscore(string input) 
{ 
    string matchedValue = 
     Regex.Match(input, "(?<Group>.*)[_](self|ally|enemy)").Groups["Group"].ToString(); 

    return matchedValue; 
} 
0

Je ne peux pas encore des commentaires à l'autre réponse par Macy Abbey, donc voilà:

Si vous voulez seulement faire correspondre le mot à la fin vous devez ajouter un « $ » à la fin de la chaîne de recherche:

/(.+)_(ally|self|enemy)$/ 
+0

Ah, je viens de me rendre compte que mon titre est complètement faux ... – Miguel

0

Cela fonctionne

static void Main(string[] args) 
     { 
      string [] vars= 
     new string[]{ @"data\ui\textures\generic\decorators\hero_anti_infantry_melee_2_self", 
@"data\ui\textures\generic\decorators\anti_infantry_ranged_2_ally", 
@"data\ui\textures\generic\decorators\suppression_aoe_enemy", 
@"data\ui\textures\generic\decorators\reinforce_btn_down", 
@"data\ui\textures\generic\decorators\rinset_energy", 
@"data\ui\textures\generic\decorators\suppressed" }; 

Regex re = new Regex("^(.*)_(ally|self|enemy)"); 

var xx= vars.Select(x => re.Match(x).Groups[1]); 
foreach (var y in xx) 
    Console.WriteLine(y.Value.ToString()); 
     } 
    } 
+0

Cela fonctionne sans aucun doute, mais dans ce cas j'ai simplement besoin du premier match pour devenir le résultat, indépendamment du groupement. – Miguel