Строки поиска в C#

Tip

Эта статья является частью раздела "Основы" для разработчиков , которые уже знают хотя бы один язык программирования и учат C#. Если вы не знакомы с программированием, сначала начните с учебных пособий по началу работы.

Вы пришли из другого языка? Методы C# string, такие как Contains, StartsWith и IndexOf, аналогичны методам в Java String и JavaScript String.prototype. Ключевое различие в том, что в некоторых операциях поиска в C# по умолчанию используется порядковое сравнение с учетом регистра. Другие по умолчанию используют семантику текущей культуры. Для пользовательских поисковых запросов может понадобиться передать значение StringComparison.

Класс String включает методы, которые отвечают на два повседневных вопроса:

  • Содержит ли эта строка этот текст? — использование Contains, StartsWithили EndsWith.
  • Где происходит этот текст? — использование IndexOf или LastIndexOf.

Более сложные алгоритмы поиска и замены можно создавать с помощью регулярных выражений. Дополнительные сведения о регулярных выражениях и других строковых операциях см. в статье справочника по языку Строковые операции.

Проверка того, содержит ли строка текст

Используйте Contains, StartsWithили EndsWith проверьте наличие подстроки:

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

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

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

// For user-facing searches, pass a StringComparison value to control case and culture.
bool ignoreCaseSearchResult = factMessage.StartsWith("extension", StringComparison.CurrentCultureIgnoreCase);
Console.WriteLine($"""Starts with "extension"? {ignoreCaseSearchResult} (ignoring case)""");

bool endsWithSearchResult = factMessage.EndsWith(".", StringComparison.Ordinal);
Console.WriteLine($"Ends with '.'? {endsWithSearchResult}");
// => "Extension methods have all the capabilities of regular static methods."
// => Contains "extension"? False
// => Starts with "extension"? True (ignoring case)
// => Ends with '.'? True

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

При поиске одного символа используйте перегрузку charContains. Это позволяет избежать выделения строки из одного символа и является более прямым способом:

string path = "/usr/local/bin";
bool hasSlash = path.Contains('/');
Console.WriteLine($"Path contains '/': {hasSlash}");
// => Path contains '/': True

Найдите положение текста

IndexOf возвращает отсчитываемый от нуля индекс первого вхождения подстроки (или символа) и LastIndexOf возвращает индекс последнего вхождения. Оба возвращают -1, если поисковый текст отсутствует. Объедините их для извлечения текста между двумя маркерами:

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

Console.WriteLine($"\"{factMessage}\"");

// Extract the text between the first and last occurrence of "methods".
int first = factMessage.IndexOf("methods") + "methods".Length;
int last = factMessage.LastIndexOf("methods");
string between = factMessage.Substring(first, last - first);
Console.WriteLine($"""Substring between "methods" and "methods": '{between}'""");
// => "Extension methods have all the capabilities of regular static methods."
// => Substring between "methods" and "methods": ' have all the capabilities of regular static '

Если требуется найти все вхождения, а не только первое или последнее, повторяйте поиск, передавая предыдущий результат плюс единицу в качестве аргумента startIndex, или используйте регулярное выражение.

Выбор правильного сравнения

Большинство перегрузок поиска принимают необязательное StringComparison значение. Выберите его на основе типа данных, которые вы ищете:

  • Если вы ищете идентификаторы, пути к файлам, маркеры протокола или что-либо другое, определенное компьютером, используйте Ordinal.
  • Если вы ищете машинно-определяемые данные того же типа, но хотите не учитывать регистр, используйте OrdinalIgnoreCase.
  • Если вы ищете текст, отображаемый пользователю, для которого должны применяться правила текущей локали, используйте CurrentCulture.
  • Если вы ищете тот же отображаемый пользователем текст и хотите игнорировать вариант, используйте CurrentCultureIgnoreCase.
  • Если вы выполняете поиск по сохранённым данным, которые должны сравниваться одинаково на любом компьютере независимо от языка и региональных параметров, используйте InvariantCulture (требуется редко).

Порядковое сравнение является самым быстрым вариантом и правильным значением по умолчанию для всего, что не является текстом естественного языка. Сравнение с учетом культуры значительно медленнее и может привести к удивительным результатам. Например, в некоторых культурах iстрочная буква не соответствует Iпрописной букве. Используйте это только для поисковых запросов по обычному тексту, которые выполняют пользователи.

Подробное описание сравнения с учетом языка и региональных параметров см. в рекомендациях по сравнению строк.

См. также