Delen via


Subtekenreeksen extraheren uit een tekenreeks

In dit artikel worden enkele verschillende technieken behandeld voor het extraheren van delen van een tekenreeks.

  • Gebruik de splitsmethode wanneer de gewenste subtekenreeksen worden gescheiden door een bekend scheidingsteken (of tekens).
  • Reguliere expressies zijn handig wanneer de tekenreeks voldoet aan een vast patroon.
  • Gebruik de methoden IndexOf en Subtekenreeks in combinatie als u niet alle subtekenreeksen in een tekenreeks wilt extraheren.

Methode String.Split

String.Split biedt een aantal overbelastingen waarmee u een tekenreeks kunt opsplitsen in een groep subtekenreeksen op basis van een of meer tekens die u opgeeft. U kunt ervoor kiezen om het totale aantal subtekenreeksen in het uiteindelijke resultaat te beperken, witruimtetekens te knippen uit subtekenreeksen of lege subtekenreeksen uit te sluiten.

In de volgende voorbeelden ziet u drie verschillende overbelastingen van String.Split(). In het eerste voorbeeld wordt de Split(Char[]) overbelasting aanroepen zonder scheidingstekens door te geven. Wanneer u geen scheidingstekens opgeeft, String.Split() gebruikt u standaardscheidingstekens, die spatietekens zijn, om de tekenreeks op te splitsen.

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.

Zoals u ziet, worden de punttekens (.) opgenomen in twee subtekenreeksen. Als u de punttekens wilt uitsluiten, kunt u het puntteken toevoegen als een extra scheidingsteken. In het volgende voorbeeld ziet u hoe u dit doet.

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:

De perioden zijn verdwenen uit de subtekenreeksen, maar nu zijn er twee extra lege subtekenreeksen opgenomen. Deze lege subtekenreeksen vertegenwoordigen de subtekenreeks tussen het woord en de punt die erop volgt. Als u lege subtekenreeksen uit de resulterende matrix wilt weglaten, kunt u de Split(Char[], StringSplitOptions) overbelasting aanroepen en opgeven StringSplitOptions.RemoveEmptyEntries voor de options parameter.

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

Reguliere expressies

Als uw tekenreeks voldoet aan een vast patroon, kunt u een reguliere expressie gebruiken om de elementen ervan te extraheren en te verwerken. Als tekenreeksen bijvoorbeeld de vorm 'getal operand number' hebben, kunt u een reguliere expressie gebruiken om de elementen van de tekenreeks te extraheren en te verwerken. Hier volgt een voorbeeld:

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

Het reguliere expressiepatroon (\d+)\s+([-+*/])\s+(\d+) wordt als volgt gedefinieerd:

Patroon Beschrijving
(\d+) Kom overeen met een of meer decimale cijfers. Dit is de eerste opnamegroep.
\s+ Komt overeen met een of meer spatietekens.
([-+*/]) Een rekenkundige operatorteken (+, -, *of /). Dit is de tweede vastleggende groep.
\s+ Komt overeen met een of meer spatietekens.
(\d+) Kom overeen met een of meer decimale cijfers. Dit is de derde groep die vastlegt.

U kunt ook een reguliere expressie gebruiken om subtekenreeksen uit een tekenreeks te extraheren op basis van een patroon in plaats van een vaste set tekens. Dit is een veelvoorkomend scenario wanneer een van deze voorwaarden optreedt:

  • Een of meer van de scheidingstekens dienen niet altijd als scheidingsteken in het String exemplaar.

  • De reeks en het aantal scheidingstekens is variabel of onbekend.

De Split methode kan bijvoorbeeld niet worden gebruikt om de volgende tekenreeks te splitsen, omdat het aantal \n (newline) tekens variabel is en ze niet altijd als scheidingstekens fungeren.

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

Een reguliere expressie kan deze tekenreeks eenvoudig splitsen, zoals in het volgende voorbeeld wordt weergegeven.

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.

Het reguliere expressiepatroon \[([^\[\]]+)\] wordt als volgt gedefinieerd:

Patroon Beschrijving
\[ Identiek aan een haakje openen.
([^\[\]]+) Een of meer keren overeenkomen met een willekeurig teken dat geen opening of een haakje sluiten is. Dit is de eerste opnamegroep.
\] Sluit een haakje sluiten.

De Regex.Split methode is bijna identiek aan String.Split, behalve dat er een tekenreeks wordt gesplitst op basis van een normaal expressiepatroon in plaats van een vaste tekenset. In het volgende voorbeeld wordt bijvoorbeeld de Regex.Split methode gebruikt om een tekenreeks te splitsen die subtekenreeksen bevat die zijn gescheiden door verschillende combinaties van afbreekstreepjes en andere tekens.

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

Het reguliere expressiepatroon \s-\s?[+*]?\s?-\s wordt als volgt gedefinieerd:

Patroon Beschrijving
\s- Match een spatieteken gevolgd door een afbreekstreepje.
\s? Kom overeen met nul of één spatieteken.
[+*]? Kom overeen met nul of één exemplaar van het teken + of *.
\s? Kom overeen met nul of één spatieteken.
-\s Koppel een afbreekstreepje gevolgd door een spatieteken.

Methoden String.IndexOf en String.Substring

Als u niet geïnteresseerd bent in alle subtekenreeksen in een tekenreeks, werkt u mogelijk liever met een van de vergelijkingsmethoden voor tekenreeksen waarmee de index wordt geretourneerd waarop de overeenkomst begint. Vervolgens kunt u de Substring methode aanroepen om de gewenste subtekenreeks te extraheren. De vergelijkingsmethoden voor tekenreeksen zijn onder andere:

  • IndexOf, waarmee de op nul gebaseerde index wordt geretourneerd van het eerste exemplaar van een teken of tekenreeks in een tekenreeksexemplaren.

  • IndexOfAny, die de op nul gebaseerde index retourneert in het huidige tekenreeksexemplaren van het eerste exemplaar van een teken in een tekenmatrix.

  • LastIndexOf, waarmee de op nul gebaseerde index wordt geretourneerd van het laatste exemplaar van een teken of tekenreeks in een tekenreeksexemplaren.

  • LastIndexOfAny, die een op nul gebaseerde index retourneert in het huidige tekenreeksexemplaren van het laatste exemplaar van een teken in een tekenmatrix.

In het volgende voorbeeld wordt de IndexOf methode gebruikt om de punten in een tekenreeks te vinden. Vervolgens wordt de Substring methode gebruikt om volledige zinnen te retourneren.

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.

Zie ook