Condividi tramite


Estrarre sottostringhe da una stringa

Questo articolo illustra alcune tecniche diverse per estrarre parti di una stringa.

  • Utilizzare il metodo Split quando le sottostringhe sono separate da uno o più caratteri di delimitazione noti.
  • Le espressioni regolari sono utili quando la stringa è conforme a un criterio fisso.
  • Usare i metodi IndexOf e Substring insieme quando non si desidera estrarre tutte le sottostringhe di una stringa.
  • Usare intervalli e indici in C# per estrarre o tagliare caratteri in posizioni note.

Metodo String.Split

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

Gli esempi seguenti illustrano tre diversi sovraccarichi di String.Split(). Il primo esempio chiama l'overload Split(Char[]) senza utilizzare caratteri separatori. Se non si specificano caratteri di delimitazione, String.Split() usa i delimitatori predefiniti, ovvero spazi vuoti, per dividere 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 delle sottostringhe. Se si vogliono escludere i caratteri punto, è possibile aggiungere il punto come delimitatore aggiuntivo. L'esempio successivo illustra come effettuare 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 stati rimossi dalle sottostringhe, ma sono state incluse due sottostringhe aggiuntive vuote. Le sottostringhe vuote rappresentano la sottostringa fra la parola e il punto che la segue. Per omettere le sottostringhe vuote dalla matrice risultante, è possibile chiamare l'overload Split(Char[], StringSplitOptions) e specificare StringSplitOptions.RemoveEmptyEntries per il parametro 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

Espressioni regolari

Se la stringa è conforme a un criterio fisso, è possibile usare un'espressione regolare per estrarre e gestire i relativi elementi. Ad esempio, se le stringhe accettano il formato "numerooperandonumero", è possibile usare un'espressione regolare per estrarre e gestire i relativi elementi. 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($"{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

Il modello (\d+)\s+([-+*/])\s+(\d+) dell'espressione regolare viene definito in questo modo:

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

È anche possibile usare un'espressione regolare per estrarre sottostringhe da una stringa in base a un criterio anziché a un set fisso di caratteri. Questo scenario è comune quando si verifica una di queste condizioni:

  • Uno o più caratteri delimitatori non fungono sempre da delimitatori nell'istanza di String.

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

Ad esempio, il metodo Split non può essere usato per dividere la stringa seguente, perché i caratteri \n (nuova riga) sono in numero variabile e non sempre fungono da 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ò dividere facilmente questa 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($"{++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 modello \[([^\[\]]+)\] dell'espressione regolare viene definito in questo modo:

Modello Descrizione
\[ Trova una parentesi quadra aperta.
([^\[\]]+) Collega qualsiasi carattere che non sia una parentesi aperta o chiusa una o più volte. Questo è il primo gruppo di cattura.
\] Trova una parentesi chiusa.

Il metodo Regex.Split è quasi identico a String.Split, ad eccezione del fatto che divide una stringa in base a un criterio di espressione regolare anziché a un set di caratteri fisso. Nell'esempio seguente viene utilizzato il metodo Regex.Split per dividere una stringa contenente sottostringhe delimitate da varie 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 - + - 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

Il modello \s-\s?[+*]?\s?-\s dell'espressione regolare viene definito in questo modo:

Modello Descrizione
\s- Trova uno spazio vuoto seguito da un trattino.
\s? Corrispondi zero o uno carattere di spazio bianco.
[+*]? Trova zero o una occorrenza del carattere + o *.
\s? Corrispondi zero o uno carattere di spazio bianco.
-\s Trova un trattino seguito da uno spazio vuoto.

Metodi String.IndexOf e String.Substring

Se non si è interessati a tutte le sottostringhe di una stringa, è consigliabile usare uno dei metodi di confronto tra stringhe che restituisce l'indice in cui inizia la corrispondenza. È quindi possibile chiamare il metodo Substring 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 della prima occorrenza di qualsiasi carattere di una matrice di caratteri nell'istanza di stringa corrente.

  • 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 l'indice in base zero dell'ultima occorrenza di qualsiasi carattere di una matrice di caratteri nell'istanza di stringa corrente.

L'esempio seguente usa il metodo IndexOf per trovare i punti in una stringa. Usa quindi il metodo Substring 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.

Gli intervalli e indici

L'operatore ..range C# e l'operatore ^index-from-end consentono di estrarre sottostringhe usando una sintassi concisa. È possibile applicare questi operatori direttamente alle stringhe senza chiamare Substring.

L'esempio seguente illustra diversi modi per estrarre parti di una stringa usando intervalli:

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

Nell'esempio seguente viene usato l'operatore index-from-end per rimuovere un'estensione di file (gli ultimi tre caratteri) da un percorso:

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

Annotazioni

Gli intervalli e l'operatore index-from-end sono funzionalità C#. Visual Basic non supporta questa sintassi; usare Substring invece .

Vedi anche