Извлечение подстрок из строки
В этой статье рассматриваются различные методы извлечения частей строки.
- Используйте метод Split, если нужные подстроки разделены символом-разделителем (или символами).
- Регулярные выражения удобно использовать, когда строка соответствует фиксированному шаблону.
- Используйте сочетание методов IndexOf и Substring, если не хотите извлекать все подстроки из строки.
Метод String.Split
String.Split предоставляет несколько перегрузок, которые позволяют разбить строку на группу подстрок, основанных на одном или нескольких указанных символах-разделителях. Вы можете ограничить общее число подстрок в окончательном результате, обрезав пробелы в подстроках или исключив пустые подстроки.
Ниже показаны три различные перегрузки String.Split()
. Первый пример вызывает перегрузку Split(Char[]) без передачи знаков разделения. Если не указать символы-разделители, String.Split()
будет использовать для разделения строки разделители по умолчанию, которые являются пробелами.
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.
Как видите, символы-точки (.
) содержатся в двух подстроках. Если вы хотите исключить символы-точки, добавьте символ-точку как дополнительный символ разделителя. В следующем примере показано, как это сделать.
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:
Точки исчезли из подстрок, однако теперь появились две дополнительные пустые подстроки. Пустые подстроки представляют подстроку между словом и точкой после него. Чтобы исключить из результирующего массива пустые подстроки, вызовите перегрузку Split(Char[], StringSplitOptions) и укажите StringSplitOptions.RemoveEmptyEntries для параметра 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
Регулярные выражения
Если строка соответствует фиксированному шаблону, используйте регулярное выражение для извлечения и обработки ее элементов. Например, если строки имеют форму "номер операнд номер", тогда для извлечения и обработки элементов строки можно использовать регулярное выражение. Приведем пример:
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
Шаблон регулярного выражения (\d+)\s+([-+*/])\s+(\d+)
определяется следующим образом:
Расписание | Description |
---|---|
(\d+) |
Совпадение с одной или несколькими десятичными цифрами. Это первая группа записи. |
\s+ |
Совпадение с одним или несколькими пробелами. |
([-+*/]) |
Совпадение со знаком арифметического оператора (+, -, *, или /). Это вторая группа записи. |
\s+ |
Совпадение с одним или несколькими пробелами. |
(\d+) |
Совпадение с одной или несколькими десятичными цифрами. Это третья группа записи. |
Вы также можете использовать регулярное выражение для извлечения подстрок из строки на основе шаблона, а не фиксированного набора символов. Это распространенный сценарий, если происходит одно из следующих условий:
Один или несколько символов-разделителей не всегда служат разделителями в экземпляре String.
Последовательность и количество символов-разделителей являются изменяемыми или неизвестными.
Например, метод Split нельзя использовать для разделения следующей строки, поскольку число символов \n
(новая строка) является изменяемым и они не всегда являются разделителями.
[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 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.
Шаблон регулярного выражения \[([^\[\]]+)\]
определяется следующим образом:
Расписание | Description |
---|---|
\[ |
Совпадение с открывающей скобой. |
([^\[\]]+) |
Совпадение с любым символом, который не является открывающей или закрывающей скобкой, один или несколько раз. Это первая группа записи. |
\] |
Совпадение с закрывающей скобкой. |
Метод Regex.Split практически идентичен методу String.Split, за исключением того, что он разделяет строку на основе шаблона регулярного выражения, а не фиксированной кодировки. Например, в следующем примере метод Regex.Split используется для разделения строки, которая содержит подстроки, разделенные с помощью различных сочетаний дефисов и других символов.
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
Шаблон регулярного выражения \s-\s?[+*]?\s?-\s
определяется следующим образом:
Расписание | Description |
---|---|
\s- |
Совпадение с пробелом, за которым следует дефис. |
\s? |
Совпадение с нулем или одним символом пробела. |
[+*]? |
Совпадение с нулем или единичное появление символа + или *. |
\s? |
Совпадение с нулем или одним символом пробела. |
-\s |
Совпадение с дефисом, за которым следует пробел. |
Методы String.IndexOf и String.Substring
Если вам нужны все подстроки в строке, можете использовать один из методов сравнения строк, которые возвращают индекс начала сопоставления. Затем для извлечения нужных подстрок можно будет вызвать метод Substring. К методам сравнения строк можно отнести:
IndexOf, возвращающий отсчитываемый от нуля индекс первого появления символа или строки в экземпляре строки.
IndexOfAny, возвращающий отсчитываемый от нуля индекс в текущем экземпляре строки первого появления любого символа в массиве символов.
LastIndexOf, возвращающий отсчитываемый от нуля индекс последнего появления символа или строки в экземпляре строки.
LastIndexOfAny, возвращающий отсчитываемый от нуля индекс в текущем экземпляре строки последнего вхождения любого символа в массиве символов.
В следующем примере метод IndexOf используется для поиска точек в строке. После чего в нем используется метод Substring для возврата полных предложений.
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.