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 de divisão quando as substrings forem separadas por um ou mais caracteres delimitadores conhecidos.
- 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 diversas sobrecargas para ajudar você a dividir uma cadeia de caracteres em um grupo de substrings com base em um ou mais caracteres delimitadores especificados. É possível 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 chama a sobrecarga Split(Char[]) sem transmitir caracteres separadores. Quando nenhum caractere delimitador é especificado, String.Split()
usa delimitadores padrã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.
Os caracteres de ponto (.
) estão incluídos em duas das substrings. Para excluir caracteres de ponto, adicione-os como caracteres delimitadores adicionais. 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 pontos sumiram das substrings, mas duas substrings vazias extras foram incluídas agora. Essas substrings vazias representam a substring entre a palavra e o ponto que a segue. Para omitir substrings vazias da matriz resultante, é possível chamar a sobrecarga Split(Char[], StringSplitOptions) e especificar StringSplitOptions.RemoveEmptyEntries para o parâmetro 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
Expressões regulares
Se a cadeia de caracteres estiver em conformidade com um padrão fixo, será possível usar uma expressão regular para extrair e manipular seus elementos. Por exemplo, se as cadeias de caracteres assumirem a forma "número operando número", você poderá usar uma expressão regular para extrair e manipular os elementos da cadeia de caracteres. Veja 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 de expressão regular (\d+)\s+([-+*/])\s+(\d+)
é definido da seguinte forma:
Padrão | Descrição |
---|---|
(\d+) |
Corresponde a um ou mais dígitos decimais. Este é o primeiro grupo de captura. |
\s+ |
Corresponde a um ou mais caracteres de espaço em branco. |
([-+*/]) |
Corresponde a um sinal de operador aritmético (+, -, * ou /). Este é o segundo grupo de captura. |
\s+ |
Corresponde a um ou mais caracteres de espaço em branco. |
(\d+) |
Corresponde a um ou mais dígitos decimais. Este é o terceiro grupo de captura. |
Também é possível usar uma expressão regular para extrair substrings de uma cadeia de caracteres com base em um padrão em vez de em um conjunto fixo de caracteres. Este é um cenário comum em qualquer uma destas condições:
Um ou mais dos caracteres delimitadores nem sempre servem como delimitadores na instância String.
A sequência e o número de caracteres delimitadores são variáveis ou desconhecidos.
Por exemplo, o método Split não pode ser usado para dividir a cadeia de caracteres a seguir, pois o número de caracteres \n
(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 da seguinte forma:
Padrão | Descrição |
---|---|
\[ |
Corresponde a um colchete de abertura. |
([^\[\]]+) |
Corresponde a qualquer caractere que não seja um colchete de abertura ou fechamento uma ou mais vezes. Este é o primeiro grupo de captura. |
\] |
Corresponde a um colchete de fechamento. |
O método Regex.Split é quase idêntico a String.Split, mas divide uma cadeia de caracteres com base em um padrão de expressão regular em vez de em um conjunto de caracteres fixo. Por exemplo, o exemplo a seguir usa o método Regex.Split para dividir uma cadeia de caracteres que contém substrings delimitadas por diversas combinações de hifens 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 de expressão regular \s-\s?[+*]?\s?-\s
é definido da seguinte forma:
Padrão | Descrição |
---|---|
\s- |
Corresponde a um caractere de espaço em branco seguido por um hífen. |
\s? |
Corresponder a zero ou a um caractere de espaço em branco. |
[+*]? |
Corresponde a nenhuma ou uma ocorrência do caractere + ou *. |
\s? |
Corresponder a zero ou a um caractere de espaço em branco. |
-\s |
Corresponde a um hífen seguido por 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 cadeia de caracteres, talvez prefira trabalhar com um dos métodos de comparação de cadeia de caracteres que retornam o índice que inicia a correspondência. Em seguida, é possível chamar o método Substring 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 instância da cadeia.
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 instância da cadeia.
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 método IndexOf para localizar os pontos em uma cadeia de caracteres. Em seguida, ele usa o método Substring 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.