J'ai été incapable de trouver une réponse à ce sujet: puis-je utiliser la méthode Regex.Matches
pour ne renvoyer que le contenus des éléments avec des accolades?
Si j'utilise Regex ({[^}]*})
, ma valeur MatchCollection
inclut les accolades. Je veux faire correspondre, mais alors seulement renvoyer le contenu. Voici ce que j'ai jusqu'à présent:
Regex regex = new Regex(({[^}]*}), RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches("Test {Token1} {Token 2}");
// Results include braces (undesirable)
var results = matches.Cast<Match>().Select(m => m.Value).Distinct().ToList();
Je l'ai toujours aimé explicite. Vous pouvez donc utiliser les groupes "positif lookbehind" (? <= ...) et "positif lookahead" (? = ...):
(?<=\{)
[^}]*
(?=\})
ce qui signifie:
En C #, comme dans de nombreux autres langages de programmation, le moteur des expressions rationnelles prend en chargegroupes de capture, qui sont sous-correspondances, des parties de sous-chaînes correspondant à un motif de regex complet, défini dans un motif regex à l’aide de parenthèses (par exemple, 1([0-9])3
correspond à 123
et enregistre la valeur de 2
dans un tampon du groupe de capture 1). Les textes capturés sont accessibles via Match.Groups[n].Value
où n est l’index du groupe de capture à l’intérieur du motif.
La capture est beaucoup plus efficace que les lookarounds . Lorsque des conditions complexes ne sont pas nécessaires, les groupes de capture sont de bien meilleures alternatives.
Voir mon test de vitesse regex effectué sur regexhero.net:
Maintenant, comment pouvons-nous obtenir la sous-chaîne entre accolades?
{([^{}]*)
{((?>[^{}]+|{(?<c>)|}(?<-c>))*(?(c)(?!)))
Dans les deux cas, nous correspondons à un {
d'ouverture, puis à (1) tout caractère autre que {
ou }
, ou (2) tous les caractères jusqu'au premier }
apparié.
Voici exemple de code :
var matches = Regex.Matches("Test {Token1} {Token 2}", @"{([^{}]*)");
var results = matches.Cast<Match>().Select(m => m.Groups[1].Value).Distinct().ToList();
Console.WriteLine(String.Join(", ", results));
matches = Regex.Matches("Test {Token1} {Token {2}}", @"{((?>[^{}]+|{(?<c>)|}(?<-c>))*(?(c)(?!)))");
results = matches.Cast<Match>().Select(m => m.Groups[1].Value).Distinct().ToList();
Console.WriteLine(String.Join(", ", results));
Résultat: Token1, Token 2
, Token1, Token {2}
.
Notez que RegexOptions.IgnoreCase
est redondant lorsque vous n'avez aucune lettre littérale pouvant avoir une casse différente dans le modèle.
Merci Milosz Krajewski, Rien à ajouter mais voici la fonction
private List<String> GetTokens(String str)
{
Regex regex = new Regex(@"(?<=\{)[^}]*(?=\})", RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(str);
// Results include braces (undesirable)
return matches.Cast<Match>().Select(m => m.Value).Distinct().ToList();
}
Il suffit de déplacer les accolades en dehors des parenthèses:
{([^}]*)}
C'est regex pour C # .net.
@"{(.*?)}"
il affiche un
jeton1 jeton2
Si je comprends ce que tu veux. Changez l'expression régulière en {([^}]*)}
. Cela ne fera que capturer le texte entre {}, sans les inclure.
Peu modifiant la réponse de @Milosz Krajewski
(?<=\{)[^}{]*(?=\})
cela permettra d’éviter les accolades fermées dans la ficelle.