Практическое руководство. Поиск по строкам

Существует две основные стратегии для поиска текста в строках. Методы класса String выполняют поиск определенного текста. Регулярные выражения используются для поиска шаблонов в тексте.

Примечание.

Примеры C# в этой статье выполняются во встроенном средстве выполнения кода и на площадке Try.NET. Нажмите на кнопку Выполнить, чтобы выполнить пример в интерактивном окне. После выполнения кода вы можете изменить его и выполнить измененный код, снова нажав на кнопку Выполнить. Либо в интерактивном окне выполняется измененный код, либо, если компиляция завершается с ошибкой, в интерактивном окне отображаются все сообщения об ошибках компилятора C#.

Тип string является псевдонимом класса System.String и реализует ряд полезных методов для поиска содержимого строк. Среди них: Contains, StartsWith, EndsWith, IndexOf, LastIndexOf. Класс System.Text.RegularExpressions.Regex предоставляет широкие возможности словаря для поиска шаблонов в тексте. В этой статье вы узнаете, как применять эти методы и как выбрать наилучший способ в зависимости от ваших потребностей.

Содержит ли строка текст?

Методы String.Contains, String.StartsWith и String.EndsWith выполняют поиск определенного текста в строке. В следующем примере показано использование каждого из этих методов, а также сценарии поиска без учета регистра:

string factMessage = "Extension methods have all the capabilities of regular static methods.";

// Write the string and include the quotation marks.
Console.WriteLine($"\"{factMessage}\"");

// Simple comparisons are always case sensitive!
bool containsSearchResult = factMessage.Contains("extension");
Console.WriteLine($"Contains \"extension\"? {containsSearchResult}");

// For user input and strings that will be displayed to the end user,
// use the StringComparison parameter on methods that have it to specify how to match strings.
bool ignoreCaseSearchResult = factMessage.StartsWith("extension", System.StringComparison.CurrentCultureIgnoreCase);
Console.WriteLine($"Starts with \"extension\"? {ignoreCaseSearchResult} (ignoring case)");

bool endsWithSearchResult = factMessage.EndsWith(".", System.StringComparison.CurrentCultureIgnoreCase);
Console.WriteLine($"Ends with '.'? {endsWithSearchResult}");

В предыдущем примере показано важное правило использования этих методов. По умолчанию поиск выполняется с учетом регистра. Чтобы выполнить поиск без учета регистра, используйте значение перечисления StringComparison.CurrentCultureIgnoreCase.

Где искомый текст находится в строке?

Методы IndexOf и LastIndexOf также ищут текст в строках. Эти методы возвращают расположение текста, поиск которого выполняется. Если текст не найден, возвращается -1. В следующем примере происходит поиск первого и последнего вхождения слова "methods" и отображение текста, находящегося между ними.

string factMessage = "Extension methods have all the capabilities of regular static methods.";

// Write the string and include the quotation marks.
Console.WriteLine($"\"{factMessage}\"");

// This search returns the substring between two strings, so
// the first index is moved to the character just after the first string.
int first = factMessage.IndexOf("methods") + "methods".Length;
int last = factMessage.LastIndexOf("methods");
string str2 = factMessage.Substring(first, last - first);
Console.WriteLine($"Substring between \"methods\" and \"methods\": '{str2}'");

Поиск определенного текста с помощью регулярных выражений

Класс System.Text.RegularExpressions.Regex можно использовать для поиска строк. Такой поиск может отличаться по сложности от самых простых до очень сложных текстовых шаблонов.

В следующем примере кода выполняется поиск слов "the" и "their" в предложении без учета регистра. Статический метод Regex.IsMatch выполняет поиск. В метод передается строка и шаблон поиска. В нашем примере третий аргумент задает поиск без учета регистра. Дополнительные сведения см. в разделе System.Text.RegularExpressions.RegexOptions.

Шаблон поиска описывает текст для поиска. Следующая таблица описывает каждый элемент шаблона поиска. (В таблице ниже используется один \, который в строке C# необходимо экранировать как \\).

Расписание Значение
the соответствует тексту "the"
(eir)? Соответствует 0 или 1 вхождению "eir"
\s Соответствует пробелу.
string[] sentences =
{
    "Put the water over there.",
    "They're quite thirsty.",
    "Their water bottles broke."
};

string sPattern = "the(ir)?\\s";

foreach (string s in sentences)
{
    Console.Write($"{s,24}");

    if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase))
    {
        Console.WriteLine($"  (match for '{sPattern}' found)");
    }
    else
    {
        Console.WriteLine();
    }
}

Совет

Методы string обычно удобнее при поиске точного совпадения со строкой. Регулярные выражения больше подходят при поиске определенных шаблонов в исходной строке.

Соответствует ли строка шаблону?

В следующем коде реализуется проверка формата каждой строки в массиве с использованием регулярных выражений. По условиям проверки каждая строка должна иметь формат номера телефона: три группы цифр, разделенных дефисами. Первые две группы содержат по три цифры, и третья группа состоит из четырех цифр. Шаблон поиска использует регулярное выражение ^\\d{3}-\\d{3}-\\d{4}$. Дополнительные сведения см. в разделе Элементы языка регулярных выражений. Краткий справочник.

Расписание Значение
^ соответствует началу строки
\d{3} соответствует в точности 3 цифрам
- соответствует символу "–"
\d{4} соответствует в точности 4 цифрам
$ соответствует концу строки
string[] numbers =
{
    "123-555-0190",
    "444-234-22450",
    "690-555-0178",
    "146-893-232",
    "146-555-0122",
    "4007-555-0111",
    "407-555-0111",
    "407-2-5555",
    "407-555-8974",
    "407-2ab-5555",
    "690-555-8148",
    "146-893-232-"
};

string sPattern = "^\\d{3}-\\d{3}-\\d{4}$";

foreach (string s in numbers)
{
    Console.Write($"{s,14}");

    if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern))
    {
        Console.WriteLine(" - valid");
    }
    else
    {
        Console.WriteLine(" - invalid");
    }
}

Один шаблон поиска соответствует множеству допустимых строк. Регулярные выражения больше подходят для поиска или проверки соответствия шаблону, а не для поиска отдельной строки текста.

См. также