3
votes

Groupes de capture d'expressions régulières

Avec l'expression régulière suivante:

\s*,\s*(\w*)

et la chaîne de test:

Full match: InitValue(Input1, Input2, ..., Inputn)
Group1: Input1
Group2: Input2
....
Groupn: Inputn

j'obtiens le résultat suivant:

Full match: InitValue(Input1, Input2)
Group1: Input1
Group2: Input2

Avec l'expression régulière suivante:

InitValue(Input1, Input2)

et la chaîne de test:

InitValue\((\w*)\s*,\s*(\w*)\)

J'obtiens:

Full match: InitValue(Input1)
Group1: Input1

Maintenant, je voudrais capturer n'importe quel nombre d'arguments de la méthode InitValue. Le nombre d'arguments de InitValue est inconnu.

InitValue(Input1)

Bien sûr, je ne peux pas répéter le modèle suivant dans mon expression régulière car je ne connais pas le nombre d'arguments à l'avance:

InitValue\((\w*)\)

Comment écrire une expression régulière qui génère n nombre de groupes de capture?

J'utilise l'expression régulière en C # -code (Regex, Match) ...


0 commentaires

4 Réponses :


0
votes

Ne laissez personne vous dire ce que c'est impossible et ce que ce n'est pas

entrez la description de l'image ici

Vous devrez le toucher un peu mais je pense qu'il peut vous guider = D.

Modifier, en répondant à votre question. b.Count vous donnera le nombre de correspondances.
Edit 2, je poste l'image pour afficher les informations de débogage. Mais voici le code pour le sibariste.

string input = "InitValue(test, othertest, bleh, blehTest, foo)";

Regex regArgs = new Regex(@"(?:InitValue\()(.*)(?:\))");
Match matchArgs = regArgs.Match(input);

string valueArgs = matchArgs.Groups[1].Value;

Regex reg = new Regex(@"[\w]+");

MatchCollection b = reg.Matches(valueArgs);

string b1 = b[0].Value;
string b2 = b[1].Value;

int numberGroups = b.Count;

Edit 3, comme suggéré dans le commentaire c'est la solution complète, vous devrez effacer le Partie InitValue (*) avec un autre Regex ou avec une Substring

string bar = "test, othertest";
Regex reg = new Regex(@"[\w]+");

MatchCollection b = reg.Matches(bar);

string b1 = b[0].Value;
string b2 = b[1].Value;

int numberGroups = b.Count;


2 commentaires

Veuillez montrer comment appliquer cette technique à la chaîne de test: InitValue (Input1, Input2, Input3, Input4)


Que voulez-vous dire? Comme je l'ai dit, ce n'est qu'une illustration, pas la solution complète, mais assez proche. Vous pouvez facilement supprimer la InitValue (*) avec une Substring et conserver les arguments, si vous voulez dire que c'est impossible quand c'est écrit InitValue, alors oui, vous avez raison, mais c'est loin d'être impossible = D



1
votes

Il est possible de le faire dans .NET - vous utilisez un seul Groupe de capture, puis vous accédez à la collection Captures du groupe pour voir tous les éléments capturés, pas seulement la valeur finale.

Vous devrez écrire une expression régulière qui peut répéter le groupe de correspondance d'arguments, quelque chose comme

InitValue\((?:(\w+)\s*(?:,(?!\s*\))|(?=\s*\)))\s*)*\)

Jouez avec la Démo Debuggex pour qu'elle corresponde à ce que vous voulez. P >


0 commentaires

1
votes
static void GetParams()
{
    int x = 0;
    var strings = new[]
    {
        "InitValue()",
        "InitValue(Input1)",
        "InitValue(Input1, Input2, Input3, Input4)"
    };

    var pattern = @"(\w+)\((?:(\w+)(?:,?\s*))*\)";

    foreach (var s in strings)
    {
        WriteLine($"String: '{s}'");
        var match = Regex.Match(s, pattern);
        if (match.Success)
        {
            WriteLine($"\tMethod: '{match.Groups[1].Value}'");
            WriteLine("\tParameters:");
            var captures = match.Groups[2].Captures;
            if (captures.Count > 0)
            {
                x = 0;
                foreach (Capture capture in captures)
                {
                    WriteLine($"\t\tParam {++x}: '{capture.Value}'");
                }
            }
            else
            {
                WriteLine("\t\tNo params found.");
            }

            WriteLine();
        }

        else
            WriteLine("No matches found.");
    }
}

/*
Output:

String: 'InitValue()'
        Method: 'InitValue'
        Parameters:
                No params found.

String: 'InitValue(Input1)'
        Method: 'InitValue'
        Parameters:
                Param 1: 'Input1'

String: 'InitValue(Input1, Input2, Input3, Input4)'
        Method: 'InitValue'
        Parameters:
                Param 1: 'Input1'
                Param 2: 'Input2'
                Param 3: 'Input3'
                Param 4: 'Input4'
*/

0 commentaires

1
votes

.NET prend en charge la recherche infinie derrière (? . Au lieu d'obtenir des groupes de capture, une autre option pourrait être d'obtenir les correspondances à la place:

Input1
Input2
Input3

Explication

  • (? Lookbehind positif, vérifiez ce qui est sur la gauche correspond:
    • \ bInitValue \ ([^ ()] * Correspondre au wordboundary, InitValue ( puis 0+ fois aucun des ( ou )
  • ) Fermer la recherche positive
  • [^, \ t] + Classe de caractères négatifs, correspond à plus de 1 fois sans espace ni virgule
  • (? = Recherche positive pour vérifier ce qu'il y a sur les bonnes correspondances:
    • [^ ()] * \) Correspond à 0 fois ou plus aucun des ( ou ) , puis correspond à )
  • ) Fermer la recherche positive
  • Par exemple:

    string pattern = @"(?<=\bInitValue\([^()]*)[^, ]+(?=[^()]*\))";
    string str = "InitValue(Input1, Input2, Input3)";            
    foreach (Match m in Regex.Matches(str, pattern))
    {
        Console.WriteLine(m.Value);
    }
    

    Résultat

    (?<=\bInitValue\([^()]*)[^, ]+(?=[^()]*\))
    

    Voir le Démo Regex | Démo C #


    0 commentaires