Estrai sottostringhe da una stringa

Questo articolo illustra alcune tecniche diverse per l'estrazione di parti di una stringa.

  • Usare il metodo Split quando le sottostringhe desiderate sono separate da un carattere di delimitazione noto (o caratteri).
  • Le espressioni regolari sono utili quando la stringa è conforme a un modello fisso.
  • Usare i metodi IndexOf e substring insieme quando non si vuole estrarre tutte le sottostringhe in una stringa.

String. Split (metodo)

String.Split in sono disponibili alcuni overload che consentono di suddividere una stringa in un gruppo di sottostringhe in base a uno o più caratteri di delimitazione specificati. È possibile scegliere di limitare il numero totale di sottostringhe nel risultato finale, tagliare gli spazi vuoti dalle sottostringhe o escludere le sottostringhe vuote.

Negli esempi seguenti vengono illustrati tre overload diversi di String.Split() . Nel primo esempio viene chiamato l' Split(Char[]) Overload senza passare alcun carattere separatore. Quando non si specifica alcun carattere di delimitazione, String.Split() Usa i delimitatori predefiniti, che sono spazi vuoti, per suddividere la stringa.

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.

Come si può notare, i caratteri punto ( . ) sono inclusi in due sottostringhe. Se si desidera escludere i caratteri del periodo, è possibile aggiungere il carattere punto come carattere di delimitazione aggiuntivo. Nell'esempio seguente viene illustrato come eseguire questa operazione.

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:

I punti sono passati dalle sottostringhe, ma ora sono state incluse due sottostringhe vuote aggiuntive. Questa sottostringa vuota rappresenta la sottostringa tra la parola e il periodo che lo segue. Per omettere le sottostringhe vuote dalla matrice risultante, è possibile chiamare l' Split(Char[], StringSplitOptions) Overload e specificare StringSplitOptions.RemoveEmptyEntries per il options parametro.

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

Espressioni regolari

Se la stringa è conforme a un modello fisso, è possibile usare un'espressione regolare per estrarne e gestirne gli elementi. Se, ad esempio, le stringhe hanno il formato "numero operando number Number", è possibile usare un' espressione regolare per estrarre e gestire gli elementi della stringa. Ecco un esempio:

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

Il criterio di ricerca di espressioni regolari (\d+)\s+([-+*/])\s+(\d+) è definito come segue:

Modello Descrizione
(\d+) Trova la corrispondenza con una o più cifre decimali. Equivale al primo gruppo di acquisizione.
\s+ Corrisponde a uno o più spazi vuoti.
([-+*/]) Corrisponde a un segno di operatore aritmetico (+,-, * o/). Equivale al secondo gruppo di acquisizione.
\s+ Corrisponde a uno o più spazi vuoti.
(\d+) Trova la corrispondenza con una o più cifre decimali. Equivale al terzo gruppo di acquisizione.

È anche possibile usare un'espressione regolare per estrarre le sottostringhe da una stringa basata su un modello anziché su un set fisso di caratteri. Si tratta di uno scenario comune quando si verifica una delle condizioni seguenti:

  • Uno o più caratteri delimitatore non vengono sempre utilizzati come delimitatore nell' String istanza.

  • La sequenza e il numero di caratteri delimitatori sono variabili o sconosciute.

Il metodo, ad esempio, Split non può essere usato per suddividere la stringa seguente, perché il numero di \n caratteri di nuova riga è variabile e non sempre come delimitatori.

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

Un'espressione regolare può suddividere facilmente la stringa, come illustrato nell'esempio seguente.

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.

Il criterio di ricerca di espressioni regolari \[([^\[\]]+)\] è definito come segue:

Modello Descrizione
\[ Corrisponde a una parentesi di apertura.
([^\[\]]+) Trovare la corrispondenza con qualsiasi carattere che non sia una parentesi di apertura o di chiusura una o più volte. Equivale al primo gruppo di acquisizione.
\] Corrisponde a una parentesi di chiusura.

Il Regex.Split metodo è quasi identico a String.Split , ad eccezione del fatto che suddivide una stringa in base a un modello di espressione regolare anziché a un set di caratteri fisso. Ad esempio, nell'esempio seguente viene usato il Regex.Split metodo per dividere una stringa che contiene sottostringhe delimitate da diverse combinazioni di trattini e altri caratteri.

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 - + - armoir - - 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
'       armoir
'       alarm

Il criterio di ricerca di espressioni regolari \s-\s?[+*]?\s?-\s è definito come segue:

Modello Descrizione
\s- Corrisponde a uno spazio vuoto seguito da un trattino.
\s? Trova la corrispondenza di uno o nessuno spazio vuoto.
[+*]? Trovare la corrispondenza con zero o una occorrenza del carattere + o *.
\s? Trova la corrispondenza di uno o nessuno spazio vuoto.
-\s Corrisponde a un trattino seguito da uno spazio vuoto.

Metodi String. IndexOf e String. Substring

Se non si è interessati a tutte le sottostringhe di una stringa, è preferibile usare uno dei metodi di confronto tra stringhe che restituisce l'indice in corrispondenza del quale inizia la corrispondenza. È quindi possibile chiamare il Substring metodo per estrarre la sottostringa desiderata. I metodi di confronto tra stringhe includono:

  • IndexOf, che restituisce l'indice in base zero della prima occorrenza di un carattere o di una stringa in un'istanza di stringa.

  • IndexOfAny, che restituisce l'indice in base zero nell'istanza di stringa corrente della prima occorrenza di qualsiasi carattere in una matrice di caratteri.

  • LastIndexOf, che restituisce l'indice in base zero dell'ultima occorrenza di un carattere o di una stringa in un'istanza di stringa.

  • LastIndexOfAny, che restituisce un indice in base zero nell'istanza di stringa corrente dell'ultima occorrenza di qualsiasi carattere in una matrice di caratteri.

Nell'esempio seguente viene usato il IndexOf metodo per individuare i punti in una stringa. USA quindi il Substring metodo per restituire frasi complete.

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.

Vedere anche