Extrahování podřetězců z řetězce
Tento článek popisuje některé různé techniky extrakce částí řetězce.
- Metodu Split použijte, pokud jsou podřetěžce, které chcete oddělit známým znakem oddělovače (nebo znaky).
- Regulární výrazy jsou užitečné, když řetězec odpovídá pevnému vzoru.
- Metody IndexOf a Substring použijte ve spojení, pokud nechcete extrahovat všechny podřetězce v řetězci.
String.Split – metoda
String.Split poskytuje několik přetížení, které vám pomůžou rozdělit řetězec do skupiny podřetězců na základě jednoho nebo více zadaných znaků s oddělovači. Můžete se rozhodnout omezit celkový počet podřetězců v konečném výsledku, oříznout prázdné znaky z podřetězců nebo vyloučit prázdné podřetězce.
Následující příklady ukazují tři různé přetížení String.Split()
. První příklad volá Split(Char[]) přetížení bez předání znaků oddělovače. Pokud nezadáte žádné oddělovače, String.Split()
rozdělí řetězec pomocí výchozích oddělovačů, což jsou prázdné znaky.
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.
Jak vidíte, znaky tečky (.
) jsou zahrnuty do dvou podřetěžců. Pokud chcete znaky tečky vyloučit, můžete ho přidat jako další znak oddělovače. Další příklad ukazuje, jak to udělat.
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:
Tečky jsou pryč z podřetěžců, ale nyní byly zahrnuty dva nadbytečné prázdné podřetětěce. Tyto prázdné podřetětězí představují podřetězí mezi slovem a tečkou, která za ním následuje. Chcete-li vynechat prázdné podřetězce z výsledného pole, můžete volat Split(Char[], StringSplitOptions) přetížení a určit StringSplitOptions.RemoveEmptyEntries parametr 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
Regulární výrazy
Pokud je řetězec v souladu s pevným vzorem, můžete k extrakci a zpracování jeho prvků použít regulární výraz. Pokud například řetězce mají tvar "číslo operandu", můžete k extrakci a zpracování prvků řetězce použít regulární výraz. Tady je příklad:
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
Vzor (\d+)\s+([-+*/])\s+(\d+)
regulárního výrazu je definován takto:
Vzor | Popis |
---|---|
(\d+) |
Porovná jednu nebo více desítkových číslic. Toto je první zachytávající skupina. |
\s+ |
Porovná jeden nebo více prázdných znaků. |
([-+*/]) |
Porovná znaménko aritmetického operátoru (+, -, *nebo /). Toto je druhá zachytávající skupina. |
\s+ |
Porovná jeden nebo více prázdných znaků. |
(\d+) |
Porovná jednu nebo více desítkových číslic. Toto je třetí zachytávající skupina. |
Regulární výraz můžete použít také k extrakci podřetězců z řetězce založeného na vzoru místo pevné sady znaků. Jedná se o běžný scénář, kdy dojde k některé z těchto podmínek:
Jeden nebo více znaků oddělovače nemusí v instanci vždy sloužit jako oddělovač String .
Posloupnost a počet znaků oddělovače jsou proměnné nebo neznámé.
Například metodu Split nelze použít k rozdělení následujícího řetězce, protože počet \n
znaků (newline) je proměnný a nemusí vždy sloužit jako oddělovače.
[This is captured\ntext.]\n\n[\n[This is more captured text.]\n]
\n[Some more captured text:\n Option1\n Option2][Terse text.]
Regulární výraz může tento řetězec snadno rozdělit, jak ukazuje následující příklad.
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.
Vzor \[([^\[\]]+)\]
regulárního výrazu je definován takto:
Vzor | Popis |
---|---|
\[ |
Porovná levou závorku. |
([^\[\]]+) |
Porovná libovolný znak, který není levou nebo pravou závorkou jednou nebo vícekrát. Toto je první zachytávající skupina. |
\] |
Porovná pravou závorku. |
Metoda Regex.Split je téměř identická s String.Splittím rozdílem, že rozdělí řetězec na základě vzoru regulárního výrazu místo pevné znakové sady. Například následující příklad používá metodu Regex.Split k rozdělení řetězce, který obsahuje podřetězce oddělené různými kombinacemi spojovníků a dalších znaků.
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
Vzor \s-\s?[+*]?\s?-\s
regulárního výrazu je definován takto:
Vzor | Popis |
---|---|
\s- |
Porovná prázdný znak následovaný pomlčkou. |
\s? |
Porovná žádný nebo jeden prázdný znak. |
[+*]? |
Porovná žádný nebo jeden výskyt znaku + nebo *. |
\s? |
Porovná žádný nebo jeden prázdný znak. |
-\s |
Porovná spojovník následovaný prázdným znakem. |
Metody String.IndexOf a String.Substring
Pokud vás všechny podřetězce v řetězci nezajímají, můžete raději pracovat s některou z metod porovnání řetězců, která vrátí index, na kterém začíná shoda. Potom můžete volat metodu Substring pro extrahování požadovaného podřetězce. Mezi metody porovnání řetězců patří:
IndexOf, který vrátí index založený na nule prvního výskytu znaku nebo řetězce v instanci řetězce.
IndexOfAny, který vrátí index založený na nule v aktuální řetězcové instanci prvního výskytu libovolného znaku v poli znaků.
LastIndexOf, který vrátí index založený na nule poslední výskyt znaku nebo řetězce v instanci řetězce.
LastIndexOfAny, který vrátí index založený na nule v aktuální řetězcové instanci posledního výskytu libovolného znaku v poli znaků.
Následující příklad používá metodu IndexOf k vyhledání období v řetězci. Pak použije metodu Substring k vrácení celých vět.
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.