Freigeben über


Extrahieren von Teilzeichenfolgen aus einer Zeichenfolge

In diesem Artikel werden viele Techniken zum Extrahieren von Teilen einer Zeichenfolge behandelt.

  • Verwenden Sie die Split-Methode, wenn die gewünschten Teilzeichenfolgen durch ein bekanntes Trennzeichen (oder mehrere) getrennt sind.
  • Reguläre Ausdrücke sind nützlich, wenn die Zeichenfolge einem festen Muster entspricht.
  • Verwenden Sie die Methoden IndexOf und Substring in Verbindung miteinander, wenn Sie nicht alle Teilzeichenfolgen in einer Zeichenfolge extrahieren möchten.
  • Verwenden Sie Bereiche und Indizes in C#, um Zeichen an bekannten Positionen zu extrahieren oder zu kürzen.

String.Split-Methode

String.Split bietet mehrere Überladungen, die Ihnen helfen, eine Zeichenfolge in eine Gruppe von Teilzeichenfolgen zu zerlegen, die auf einem oder mehreren von Ihnen angegebenen Trennzeichen basieren. Sie können die Gesamtanzahl der Teilzeichenfolgen im Endergebnis begrenzen, Leerzeichen aus Teilzeichenfolgen entfernen oder leere Teilzeichenfolgen ausschließen.

Die folgenden Beispiele zeigen drei verschiedene Überladungen von String.Split(). Im ersten Beispiel wird die Überladung Split(Char[]) ohne Angabe von Trennzeichen aufgerufen. Wenn Sie keine Trennzeichen angeben, verwendet String.Split() Standardtrennzeichen, bei denen es sich um Leerzeichen handelt, um die Zeichenfolge aufzuteilen.

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.

Wie Sie sehen können, sind die Punktzeichen (.) in zwei der Teilstrings enthalten. Wenn Sie die Punktzeichen ausschließen möchten, können Sie das Punktzeichen als zusätzliches Trennzeichen hinzufügen. Im nächsten Beispiel wird gezeigt, wie dies geschieht.

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:

Die Punkte sind aus den Teilzeichenfolgen verschwunden, aber jetzt wurden zwei zusätzliche leere Teilzeichenfolgen eingefügt. Diese leere Teilzeichenfolge stellt die Teilzeichenfolge zwischen dem Wort und dem darauf folgenden Punkt dar. Um leere Teilzeichenfolgen aus dem resultierenden Array auszuschließen, können Sie die Überladung Split(Char[], StringSplitOptions) aufrufen und StringSplitOptions.RemoveEmptyEntries für den Parameter options angeben.

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

Reguläre Ausdrücke

Wenn Ihre Zeichenfolge mit einem festen Muster übereinstimmt, können Sie mit einem regulären Ausdruck dessen Elemente extrahieren und verarbeiten. Wenn Zeichenfolgen zum Beispiel die Form „ZahlOperandZahl“ haben, können Sie einen regulären Ausdruck verwenden, um die Zeichenfolge zu extrahieren und die Elemente der Zeichenfolge zu verarbeiten. Ein Beispiel:

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($"{m.Value} = {value1 + value2}");
                break;
            case "-":
                Console.WriteLine($"{m.Value} = {value1 - value2}");
                break;
            case "*":
                Console.WriteLine($"{m.Value} = {value1 * value2}");
                break;
            case "/":
                Console.WriteLine($"{m.Value} = {value1 / value2:N2}");
                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

Das Muster für reguläre Ausdrücke, (\d+)\s+([-+*/])\s+(\d+), ist so definiert:

Muster Beschreibung
(\d+) Entsprechung für mindestens eine Dezimalstelle finden. Dies ist die erste Erfassungsgruppe.
\s+ Übereinstimmung mit einem oder mehreren Leerraumzeichen.
([-+*/]) Ein arithmetisches Operatorzeichen (+, -, *, oder /) abgleichen. Dies ist die zweite Erfassungsgruppe.
\s+ Übereinstimmung mit einem oder mehreren Leerraumzeichen.
(\d+) Eine oder mehrere Dezimalziffern abgleichen. Dies ist die dritte Erfassungsgruppe.

Sie können auch einen regulären Ausdruck verwenden, um Teilzeichenfolgen aus einer Zeichenfolge zu extrahieren, die auf einem Muster statt auf einem festen Satz von Zeichen basieren. Dies ist ein gängiges Szenario, wenn eine der folgenden Bedingungen zutrifft:

  • Mindestens eines der Trennzeichen dient nicht immer als Trennzeichen in der String-Instanz.

  • Sequenz und Anzahl der Trennzeichen sind variabel oder unbekannt.

Beispielsweise kann die Split-Methode nicht verwendet werden, um die folgende Zeichenfolge aufzuteilen, da die Anzahl von \n-Zeichen (Zeilenvorschub) variabel ist und sie nicht immer als Trennzeichen dienen.

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

Ein regulärer Ausdruck kann diese Zeichenfolge problemlos aufteilen, wie im folgenden Beispiel gezeigt.

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($"{++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.

Das Muster für reguläre Ausdrücke, \[([^\[\]]+)\], ist so definiert:

Muster Beschreibung
\[ Eine öffnende Klammer finden.
([^\[\]]+) Einmal oder mehrmals eine Übereinstimmung mit einem beliebigen Zeichen finden, das keine öffnende oder schließende eckige Klammer ist. Dies ist die erste Erfassungsgruppe.
\] Übereinstimmung mit einer schließenden Klammer finden.

Die Methode Regex.Split ist fast identisch mit String.Split, außer dass sie eine Zeichenfolge auf Grundlage eines Musters regulärer Ausdrücke anstelle eines festen Satzes von Zeichen aufteilt. Im folgenden Beispiel wird beispielsweise die Regex.Split-Methode verwendet, um eine Zeichenfolge mit Teilzeichenfolgen zu teilen, die durch verschiedene Kombinationen von Bindestrichen und anderen Zeichen voneinander getrennt sind.

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

Das Muster für reguläre Ausdrücke, \s-\s?[+*]?\s?-\s, ist so definiert:

Muster Beschreibung
\s- Übereinstimmung mit einem Leerzeichen gefolgt von einem Bindestrich finden.
\s? Mache ein oder kein Leerzeichen aus.
[+*]? Übereinstimmung mit null oder einem Vorkommen von entweder dem Zeichen + oder * finden.
\s? Übereinstimmen mit null oder einem Leerzeichen.
-\s Übereinstimmung mit einem Bindestrich gefolgt von einem Leerzeichen finden.

Die Methoden String.IndexOf und String.Substring

Wenn Sie nicht an allen Teilzeichenfolgen in einer Zeichenfolge interessiert sind, können Sie auch mit einer der Methoden zum Vergleichen von Zeichenfolgen arbeiten, die den Index zurückgibt, bei dem die Übereinstimmung beginnt. Sie können dann die Substring-Methode aufrufen, um die gewünschte Teilzeichenfolge zu extrahieren. Es gibt die folgenden Methoden zum Vergleichen von Zeichenfolgen:

  • IndexOf, die den auf null basierenden Index des ersten Vorkommens eines Zeichens oder einer Zeichenfolge in einer Zeichenfolgeninstanz zurückgibt.

  • IndexOfAny, die den auf null basierenden Index in der aktuellen Zeichenfolgeninstanz beim ersten Vorkommen eines beliebigen Zeichens in einem Zeichenarray zurückgibt.

  • LastIndexOf, die den auf null basierenden Index des letzten Vorkommens eines Zeichens oder einer Zeichenfolge in einer Zeichenfolgeninstanz zurückgibt.

  • LastIndexOfAny, die einen auf null basierenden Index in der aktuellen Zeichenfolgeninstanz des letzten Vorkommens eines beliebigen Zeichens in einem Zeichenarray zurückgibt.

Im folgenden Beispiel wird die IndexOf-Methode verwendet, um die Punkte in einer Zeichenfolge zu finden. Anschließend wird die Substring-Methode verwendet, um vollständige Sätze zurückzugeben.

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.

Bereiche und Indizes

Mit dem C#-Bereichsoperator .. und dem Index-vom-Ende-Operator ^ können Sie Teilzeichenfolgen mithilfe einer knappen Syntax extrahieren. Sie können diese Operatoren direkt auf Zeichenfolgen anwenden, ohne aufrufen zu müssen Substring.

Das folgende Beispiel zeigt verschiedene Möglichkeiten zum Extrahieren von Teilen einer Zeichenfolge mithilfe von Bereichen:

string str = "Hello, World!";

// Get the first 5 characters.
string hello = str[..5];
Console.WriteLine(hello);
// Output: Hello

// Get the last 6 characters.
string world = str[^6..];
Console.WriteLine(world);
// Output: World!

// Get characters from index 7 through 11 (exclusive of 12).
string substr = str[7..12];
Console.WriteLine(substr);
// Output: World

Im nächsten Beispiel wird der Index-from-End-Operator verwendet, um eine Dateierweiterung (die letzten drei Zeichen) aus einem Pfad zu entfernen:

string filePath = "C:\\Users\\user1\\bin\\fileA.cs";

// Remove the last 3 characters (.cs extension).
string trimmedPath = filePath[..^3];
Console.WriteLine(trimmedPath);
// Output: C:\Users\user1\bin\fileA

Hinweis

Bereiche und der Index-from-End-Operator sind C#-Features. Visual Basic unterstützt diese Syntax nicht; verwenden Sie Substring stattdessen.

Siehe auch