Partilhar via


Extrair substrings de uma cadeia de caracteres

Este artigo aborda algumas técnicas diferentes para extrair partes de uma cadeia de caracteres.

  • Use o método Split quando as substrings desejadas forem separadas por um caractere (ou caracteres) delimitador conhecido.
  • Expressões regulares são úteis quando a cadeia de caracteres está em conformidade com um padrão fixo.
  • Use os métodos IndexOf e Substring em conjunto quando não quiser extrair todas as substrings em uma cadeia de caracteres.

Método String.Split

String.Split fornece um punhado de sobrecargas para ajudá-lo a dividir uma cadeia de caracteres em um grupo de substrings com base em um ou mais caracteres delimitadores que você especificar. Você pode optar por limitar o número total de substrings no resultado final, cortar caracteres de espaço em branco de substrings ou excluir substrings vazias.

Os exemplos a seguir mostram três sobrecargas diferentes de String.Split(). O primeiro exemplo chama a Split(Char[]) sobrecarga sem passar nenhum caractere separador. Quando você não especifica nenhum caractere de delimitação, String.Split() usa delimitadores padrão, que são caracteres de espaço em branco, para dividir a cadeia de caracteres.

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.

Como você pode ver, os caracteres de ponto (.) estão incluídos em duas das substrings. Se quiser excluir os caracteres de período, você pode adicionar o caractere de ponto como um caractere delimitador adicional. O próximo exemplo mostra como fazer isso.

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:

Os períodos desapareceram das substrings, mas agora duas substrings vazias extras foram incluídas. Essas subcadeias vazias representam a subcadeia entre a palavra e o período que a segue. Para omitir substrings vazias da matriz resultante, você pode chamar a Split(Char[], StringSplitOptions) sobrecarga e especificar StringSplitOptions.RemoveEmptyEntries para o options parâmetro.

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

Expressões regulares

Se sua cadeia de caracteres estiver em conformidade com um padrão fixo, você poderá usar uma expressão regular para extrair e manipular seus elementos. Por exemplo, se as cadeias de caracteres assumirem a forma "número do operando número", você poderá usar uma expressão regular para extrair e manipular os elementos da cadeia de caracteres. Eis um exemplo:

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

O padrão (\d+)\s+([-+*/])\s+(\d+) de expressão regular é definido assim:

Padrão Description
(\d+) Corresponder a um ou mais dígitos decimais. Este é o primeiro grupo de captura.
\s+ Corresponder a um ou mais caracteres de espaço em branco.
([-+*/]) Corresponder a um sinal de operador aritmético (+, -, * ou /). Este é o segundo grupo de captura.
\s+ Corresponder a um ou mais caracteres de espaço em branco.
(\d+) Corresponder a um ou mais dígitos decimais. Este é o terceiro grupo de captura.

Você também pode usar uma expressão regular para extrair substrings de uma cadeia de caracteres com base em um padrão em vez de um conjunto fixo de caracteres. Este é um cenário comum quando uma destas condições ocorre:

  • Um ou mais dos caracteres delimitadores nem sempre servem como um delimitador na String instância.

  • A sequência e o número de caracteres delimitadores são variáveis ou desconhecidos.

Por exemplo, o Split método não pode ser usado para dividir a cadeia de caracteres a seguir, porque o número de \n caracteres (nova linha) é variável e eles nem sempre servem como delimitadores.

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

Uma expressão regular pode dividir essa cadeia de caracteres facilmente, como mostra o exemplo a seguir.

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.

O padrão \[([^\[\]]+)\] de expressão regular é definido assim:

Padrão Description
\[ Corresponda a um colchete de abertura.
([^\[\]]+) Corresponder a qualquer caractere que não seja um colchete de abertura ou fechamento uma ou mais vezes. Este é o primeiro grupo de captura.
\] Corresponda a um colchete de fechamento.

O Regex.Split método é quase idêntico ao String.Split, exceto que ele divide uma cadeia de caracteres com base em um padrão de expressão regular em vez de um conjunto de caracteres fixos. Por exemplo, o exemplo a seguir usa o Regex.Split método para dividir uma cadeia de caracteres que contém substrings delimitadas por várias combinações de hífenes e outros caracteres.

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

O padrão \s-\s?[+*]?\s?-\s de expressão regular é definido assim:

Padrão Description
\s- Corresponder a um caractere de espaço em branco seguido de um hífen.
\s? Corresponder a zero ou a um caractere de espaço em branco.
[+*]? Corresponder a zero ou a uma ocorrência do caractere + ou *.
\s? Corresponder a zero ou a um caractere de espaço em branco.
-\s Corresponder a um hífen seguido de um caractere de espaço em branco.

Métodos String.IndexOf e String.Substring

Se você não estiver interessado em todas as substrings em uma string, talvez prefira trabalhar com um dos métodos de comparação de string que retorna o índice no qual a correspondência começa. Em seguida, você pode chamar o Substring método para extrair a substring desejada. Os métodos de comparação de cadeia de caracteres incluem:

  • IndexOf, que retorna o índice baseado em zero da primeira ocorrência de um caractere ou cadeia de caracteres em uma ocorrência de cadeia de caracteres.

  • IndexOfAny, que retorna o índice baseado em zero na instância de cadeia de caracteres atual da primeira ocorrência de qualquer caractere em uma matriz de caracteres.

  • LastIndexOf, que retorna o índice baseado em zero da última ocorrência de um caractere ou cadeia de caracteres em uma ocorrência de cadeia de caracteres.

  • LastIndexOfAny, que retorna um índice baseado em zero na instância de cadeia de caracteres atual da última ocorrência de qualquer caractere em uma matriz de caracteres.

O exemplo a seguir usa o IndexOf método para localizar os pontos em uma cadeia de caracteres. Em seguida, usa o Substring método para retornar frases completas.

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.

Consulte também