Extraire des sous-chaînes d’une chaîne

Cet article décrit différentes techniques d’extraction de parties d’une chaîne.

  • Utilisez la méthode Split lorsque les sous-chaînes souhaitées sont séparées par un ou des caractères de délimitation connus.
  • Les expressions régulières sont utiles lorsque la chaîne est conforme à un modèle fixe.
  • Utilisez les méthodes IndexOf et Substring conjointement lorsque vous ne souhaitez pas extraire toutes les sous-chaînes d’une chaîne.

Méthode String.Split

String.Split fournit un certain nombre de surcharges pour vous aider à diviser une chaîne en un groupe de sous-chaînes en fonction d’un ou plusieurs caractères délimitants que vous spécifiez. Vous pouvez choisir de limiter le nombre total de sous-chaînes dans le résultat final, réduire les espaces blancs des sous-chaînes ou exclure les sous-chaînes vides.

Les exemples suivants montrent trois surcharges différentes de String.Split(). Le premier exemple appelle la surcharge Split(Char[]) sans passer de caractères de séparation. Lorsque vous ne spécifiez aucun caractère délimitant, String.Split() utilise les délimiteurs par défaut, qui sont les espaces blancs, pour fractionner la chaîne.

string s = "You win some. You lose some.";

string[] subs = s.Split();

foreach (string sub in subs)
{
    Console.WriteLine($"Substring: {sub}");
}

// This example produces the following output:
//
// Substring: You
// Substring: win
// Substring: some.
// Substring: You
// Substring: lose
// Substring: some.
Dim s As String = "You win some. You lose some."
Dim subs As String() = s.Split()

For Each substring As String In subs
    Console.WriteLine("Substring: {0}", substring)
Next

' This example produces the following output:
'
' Substring: You
' Substring: win
' Substring: some.
' Substring: You
' Substring: lose
' Substring: some.

Comme vous pouvez le voir, les caractères de point (.) sont inclus dans deux des sous-chaînes. Si vous souhaitez exclure les caractères de point, vous pouvez ajouter le caractère de point en tant que caractère délimitant supplémentaire. L’exemple suivant montre comment procéder.

string s = "You win some. You lose some.";

string[] subs = s.Split(' ', '.');

foreach (string sub in subs)
{
    Console.WriteLine($"Substring: {sub}");
}

// This example produces the following output:
//
// Substring: You
// Substring: win
// Substring: some
// Substring:
// Substring: You
// Substring: lose
// Substring: some
// Substring:
Dim s As String = "You win some. You lose some."
Dim subs As String() = s.Split(" "c, "."c)

For Each substring As String In subs
    Console.WriteLine("Substring: {0}", substring)
Next

' This example produces the following output:
'
' Substring: You
' Substring: win
' Substring: some
' Substring:
' Substring: You
' Substring: lose
' Substring: some
' Substring:

Les points sont exclus des sous-chaînes, mais maintenant deux sous-chaînes vides supplémentaires ont été incluses. Ces sous-chaînes vides représentent la sous-chaîne entre le mot et le point qui la suit. Pour omettre les sous-chaînes vides du tableau résultant, vous pouvez appeler la surcharge Split(Char[], StringSplitOptions) et spécifier StringSplitOptions.RemoveEmptyEntries pour le paramètre options.

string s = "You win some. You lose some.";
char[] separators = new char[] { ' ', '.' };

string[] subs = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);

foreach (string sub in subs)
{
    Console.WriteLine($"Substring: {sub}");
}

// This example produces the following output:
//
// Substring: You
// Substring: win
// Substring: some
// Substring: You
// Substring: lose
// Substring: some
Dim s As String = "You win some. You lose some."
Dim separators As Char() = New Char() {" "c, "."c}
Dim subs As String() = s.Split(separators, StringSplitOptions.RemoveEmptyEntries)

For Each substring As String In subs
    Console.WriteLine("Substring: {0}", substring)
Next

' This example produces the following output:
'
' Substring: You
' Substring: win
' Substring: some
' Substring: You
' Substring: lose
' Substring: some

Expressions régulières

Si votre chaîne est conforme à un modèle fixe, vous pouvez utiliser une expression régulière pour extraire et gérer ses éléments. Par exemple, si les chaînes prennent la forme « nombreopérandenombre », vous pouvez utiliser une expression régulière pour extraire et gérer les éléments de la chaîne. Voici un exemple :

String[] expressions = { "16 + 21", "31 * 3", "28 / 3",
                       "42 - 18", "12 * 7",
                       "2, 4, 6, 8" };
String pattern = @"(\d+)\s+([-+*/])\s+(\d+)";

foreach (string expression in expressions)
{
    foreach (System.Text.RegularExpressions.Match m in
    System.Text.RegularExpressions.Regex.Matches(expression, pattern))
    {
        int value1 = Int32.Parse(m.Groups[1].Value);
        int value2 = Int32.Parse(m.Groups[3].Value);
        switch (m.Groups[2].Value)
        {
            case "+":
                Console.WriteLine("{0} = {1}", m.Value, value1 + value2);
                break;
            case "-":
                Console.WriteLine("{0} = {1}", m.Value, value1 - value2);
                break;
            case "*":
                Console.WriteLine("{0} = {1}", m.Value, value1 * value2);
                break;
            case "/":
                Console.WriteLine("{0} = {1:N2}", m.Value, value1 / value2);
                break;
        }
    }
}

// The example displays the following output:
//       16 + 21 = 37
//       31 * 3 = 93
//       28 / 3 = 9.33
//       42 - 18 = 24
//       12 * 7 = 84
Dim expressions() As String = {"16 + 21", "31 * 3", "28 / 3",
                              "42 - 18", "12 * 7",
                              "2, 4, 6, 8"}

Dim pattern As String = "(\d+)\s+([-+*/])\s+(\d+)"
For Each expression In expressions
    For Each m As Match In Regex.Matches(expression, pattern)
        Dim value1 As Integer = Int32.Parse(m.Groups(1).Value)
        Dim value2 As Integer = Int32.Parse(m.Groups(3).Value)
        Select Case m.Groups(2).Value
            Case "+"
                Console.WriteLine("{0} = {1}", m.Value, value1 + value2)
            Case "-"
                Console.WriteLine("{0} = {1}", m.Value, value1 - value2)
            Case "*"
                Console.WriteLine("{0} = {1}", m.Value, value1 * value2)
            Case "/"
                Console.WriteLine("{0} = {1:N2}", m.Value, value1 / value2)
        End Select
    Next
Next

' The example displays the following output:
'       16 + 21 = 37
'       31 * 3 = 93
'       28 / 3 = 9.33
'       42 - 18 = 24
'       12 * 7 = 84

Le modèle d’expression régulière (\d+)\s+([-+*/])\s+(\d+) est défini comme suit :

Modèle Description
(\d+) Mettre en correspondance un ou plusieurs chiffres décimaux. Il s'agit du premier groupe de capture.
\s+ Mettre en correspondance un ou plusieurs espaces blancs.
([-+*/]) Faire correspondre un signe d’opérateur arithmétique (+, -, * ou /). Il s'agit du deuxième groupe de capture.
\s+ Mettre en correspondance un ou plusieurs espaces blancs.
(\d+) Mettre en correspondance un ou plusieurs chiffres décimaux. Il s'agit du troisième groupe de capture.

Vous pouvez également utiliser une expression régulière pour extraire des sous-chaînes d’une chaîne sur la base d’un modèle plutôt qu’un ensemble fixe de caractères. Il s’agit d’un scénario courant lorsque l’une de ces conditions se produit :

  • Un ou plusieurs caractères de délimiteur ne servent pas toujours de délimiteur dans l’instance String.

  • La séquence et le nombre de caractères délimiteurs sont variables ou inconnus.

Par exemple, la méthode Split ne peut pas être utilisée pour fractionner la chaîne suivante, car le nombre de caractères \n (nouvelle ligne) est variable, et ils ne servent pas toujours de délimiteur.

[This is captured\ntext.]\n\n[\n[This is more captured text.]\n]
\n[Some more captured text:\n   Option1\n   Option2][Terse text.]

Une expression régulière peut facilement fractionner cette chaîne, comme le montre l’exemple suivant.

String input = "[This is captured\ntext.]\n\n[\n" +
               "[This is more captured text.]\n]\n" +
               "[Some more captured text:\n   Option1" +
               "\n   Option2][Terse text.]";
String pattern = @"\[([^\[\]]+)\]";
int ctr = 0;

foreach (System.Text.RegularExpressions.Match m in
   System.Text.RegularExpressions.Regex.Matches(input, pattern))
{
    Console.WriteLine("{0}: {1}", ++ctr, m.Groups[1].Value);
}

// The example displays the following output:
//       1: This is captured
//       text.
//       2: This is more captured text.
//       3: Some more captured text:
//          Option1
//          Option2
//       4: Terse text.
Dim input As String = String.Format("[This is captured{0}text.]" +
                                  "{0}{0}[{0}[This is more " +
                                  "captured text.]{0}{0}" +
                                  "[Some more captured text:" +
                                  "{0}   Option1" +
                                  "{0}   Option2][Terse text.]",
                                  vbCrLf)
Dim pattern As String = "\[([^\[\]]+)\]"
Dim ctr As Integer = 0
For Each m As Match In Regex.Matches(input, pattern)
    ctr += 1
    Console.WriteLine("{0}: {1}", ctr, m.Groups(1).Value)
Next

' The example displays the following output:
'       1: This is captured
'       text.
'       2: This is more captured text.
'       3: Some more captured text:
'          Option1
'          Option2
'       4: Terse text.

Le modèle d’expression régulière \[([^\[\]]+)\] est défini comme suit :

Modèle Description
\[ Mettre en correspondance un crochet ouvrant.
([^\[\]]+) Faire correspondre un caractère qui n’est pas un crochet ouvrant ou fermant une ou plusieurs fois. Il s'agit du premier groupe de capture.
\] Mettre en correspondance un crochet fermant.

La méthode Regex.Split est presque identique à String.Split, sauf qu’elle fractionne une chaîne en fonction d’un modèle d’expression régulière au lieu d’un jeu de caractères fixe. Par exemple, l’exemple suivant utilise la méthode Regex.Split pour fractionner une chaîne qui contient des sous-chaînes délimitées par différentes combinaisons de traits d’union et d’autres caractères.

String input = "abacus -- alabaster - * - atrium -+- " +
               "any -*- actual - + - armoire - - alarm";
String pattern = @"\s-\s?[+*]?\s?-\s";
String[] elements = System.Text.RegularExpressions.Regex.Split(input, pattern);

foreach (string element in elements)
    Console.WriteLine(element);

// The example displays the following output:
//       abacus
//       alabaster
//       atrium
//       any
//       actual
//       armoire
//       alarm
Dim input As String = "abacus -- alabaster - * - atrium -+- " +
                    "any -*- actual - + - armoire - - alarm"
Dim pattern As String = "\s-\s?[+*]?\s?-\s"
Dim elements() As String = Regex.Split(input, pattern)
For Each element In elements
    Console.WriteLine(element)
Next

' The example displays the following output:
'       abacus
'       alabaster
'       atrium
'       any
'       actual
'       armoire
'       alarm

Le modèle d’expression régulière \s-\s?[+*]?\s?-\s est défini comme suit :

Modèle Description
\s- Mettre en correspondance un caractère d’espace blanc suivi d’un trait d’union.
\s? Mettre en correspondance zéro ou un espace blanc.
[+*]? Mettre en correspondance zéro ou une occurrence du caractère + ou *.
\s? Mettre en correspondance zéro ou un espace blanc.
-\s Mettre en correspondance un trait d’union suivi d’un caractère d’espace blanc.

Méthodes String.IndexOf et String.Substring

Si vous n’êtes pas intéressé par toutes les sous-chaînes d’une chaîne, vous préférerez peut-être utiliser l’une des méthodes de comparaison de chaînes qui retourne l’index auquel la correspondance commence. Vous pouvez ensuite appeler la méthode Substring pour extraire la sous-chaîne souhaitée. Les méthodes de comparaison de chaînes sont les suivantes :

  • IndexOf, qui retourne l’index de base zéro de la première occurrence d’un caractère ou d’une chaîne dans une instance de chaîne.

  • IndexOfAny, qui retourne l’index de base zéro dans l’instance de chaîne actuelle de la première occurrence d’un caractère dans un tableau de caractères.

  • LastIndexOf, qui retourne l’index de base zéro de la dernière occurrence d’un caractère ou d’une chaîne dans une instance de chaîne.

  • LastIndexOfAny, qui retourne un index de base zéro dans l’instance de chaîne actuelle de la dernière occurrence d’un caractère dans un tableau de caractères.

L’exemple suivant utilise la méthode IndexOf pour rechercher les points dans une chaîne. Il utilise ensuite la méthode Substring pour retourner des phrases complètes.

String s = "This is the first sentence in a string. " +
               "More sentences will follow. For example, " +
               "this is the third sentence. This is the " +
               "fourth. And this is the fifth and final " +
               "sentence.";
var sentences = new List<String>();
int start = 0;
int position;

// Extract sentences from the string.
do
{
    position = s.IndexOf('.', start);
    if (position >= 0)
    {
        sentences.Add(s.Substring(start, position - start + 1).Trim());
        start = position + 1;
    }
} while (position > 0);

// Display the sentences.
foreach (var sentence in sentences)
    Console.WriteLine(sentence);

// The example displays the following output:
//       This is the first sentence in a string.
//       More sentences will follow.
//       For example, this is the third sentence.
//       This is the fourth.
//       And this is the fifth and final sentence.
    Dim input As String = "This is the first sentence in a string. " +
                        "More sentences will follow. For example, " +
                        "this is the third sentence. This is the " +
                        "fourth. And this is the fifth and final " +
                        "sentence."
    Dim sentences As New List(Of String)
    Dim start As Integer = 0
    Dim position As Integer

    ' Extract sentences from the string.
    Do
        position = input.IndexOf("."c, start)
        If position >= 0 Then
            sentences.Add(input.Substring(start, position - start + 1).Trim())
            start = position + 1
        End If
    Loop While position > 0

    ' Display the sentences.
    For Each sentence In sentences
        Console.WriteLine(sentence)
    Next
End Sub

' The example displays the following output:
'       This is the first sentence in a string.
'       More sentences will follow.
'       For example, this is the third sentence.
'       This is the fourth.
'       And this is the fifth and final sentence.

Voir aussi