Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье рассматриваются три строковые операции: сопоставление шаблонов регулярных выражений с System.Text.RegularExpressions.Regexпоиском без выделения ReadOnlySpan<T>и выбор StringComparison значения для правильного, быстрого сравнения.
Поиск определенного текста с помощью регулярных выражений
Класс System.Text.RegularExpressions.Regex выполняет поиск строк для шаблонов, а не фиксированных подстроек. Regex.IsMatch Статический метод принимает входную строку, шаблон и необязательные RegexOptions флаги.
В следующем примере выполняется поиск каждого предложения слова илиих без учета регистра. Шаблон the(ir)?\s соответствует the необязательно ir, а затем символ пробела:
| Pattern | Значение |
|---|---|
the |
совпадает с литеральным текстом the |
(ir)? |
совпадение 0 или 1 вхождения ir |
\s |
сопоставление символа пробела |
string[] sentences =
[
"Put the water over there.",
"They're quite thirsty.",
"Their water bottles broke."
];
string pattern = @"the(ir)?\s";
foreach (string s in sentences)
{
Console.Write($"{s,28}");
if (Regex.IsMatch(s, pattern, RegexOptions.IgnoreCase))
{
Console.WriteLine($" (match for '{pattern}' found)");
}
else
{
Console.WriteLine();
}
}
Проверка строк в шаблоне
Чтобы проверить, соответствует ли весь вход фигуре, привязывите шаблон и ^$. В следующем примере проверяется, что каждая строка — номер телефона в стиле США: три цифры, три цифры, четыре цифры, разделенные дефисами:
| Pattern | Значение |
|---|---|
^ |
Соответствие началу строки |
\d{3} |
совпадают ровно три цифры символов |
- |
сопоставление литерального - символа |
\d{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 pattern = """^\d{3}-\d{3}-\d{4}$""";
foreach (string s in numbers)
{
Console.Write($"{s,14}");
Console.WriteLine(Regex.IsMatch(s, pattern) ? " - valid" : " - invalid");
}
Полный синтаксис шаблона см. в кратком справочнике по языку регулярных выражений.
Выбор между string методами и регулярными выражениями
string методы и Regex решение перекрывающихся проблем. Предпочитайте string методы, когда текст, который вы ищете, является литеральным значением, известным префиксом или суффиксом или фиксированным разделителем. Они проще читать и быстрее, потому что они не платят затраты на компиляцию и выполнение шаблона.
Regex Охват, когда целевой объект поиска является фигурой, например изменениями, необязательными группами, повторяющимися классами символов или привязкой проверки. Как правило, если вы можете написать поиск как один или два string.Contains / / StartsWithIndexOf вызова, сделайте это.
Поиск с помощью ReadOnlySpan<char>
При синтаксическом анализе больших входных данных или выполнении поиска по горячему пути выделение string.Substring для каждого вызова может string.Split доминировать.
ReadOnlySpan<char> предоставляет представление по существующей строке (или массиву или буферу стека) без копирования и MemoryExtensions предоставляет эквиваленты общих string методов на основе диапазона, включая IndexOf:
ReadOnlySpan<char> input = "key1=alpha;key2=beta;key3=gamma".AsSpan();
ReadOnlySpan<char> needle = "key2=".AsSpan();
int start = input.IndexOf(needle);
if (start >= 0)
{
ReadOnlySpan<char> rest = input[(start + needle.Length)..];
int end = rest.IndexOf(';');
ReadOnlySpan<char> value = end >= 0 ? rest[..end] : rest;
Console.WriteLine($"key2 = {value}");
}
// => key2 = beta
Поиск на основе диапазона позволяет избежать выделения, так как срезы (input[start..], rest[..end]) — это просто окна над исходными символами. Тот же подход масштабируется для синтаксического анализа списков ключевых значений, заголовков и других разделителей без вызова Substring.
Рекомендации по производительности StringComparison
Большинство string методов экземпляров имеют перегрузки, принимаюющие StringComparison значение. Такие методы, как String.Equals(String)порядковый номер по умолчанию, но String.Compare(String, String) и String.IndexOf(String) по умолчанию для текущего языка и региональных параметров. Это различие имеет два способа:
- Скорость. Порядковое сравнение — это тест байтов для байтов, который выполняется в жестких векторных циклах. Сравнение с учетом языка и региональных параметров обращается к таблице сортировки, описывает объединение символов и применяет правила для конкретного языкового стандарта. Для одного и того же входного значения это может быть более медленным порядком.
- Правильность. Сравнение с учетом культуры может сложить символы, которые вы не ожидаете (турецкий
i/I, немецкийßиssлигатуры). Это поведение подходит для сортировки имен, которые пользователь видит, но неправильно для анализа идентификаторов, путей или маркеров протокола.
Для определяемого компьютером текста, например имен файлов, URL-адресов, заголовков HTTP, идентификаторов и ключей конфигурации, передачи или StringComparison.OrdinalIgnoreCase явного передачиStringComparison.Ordinal. Резервировать значения с учетом языка и региональных параметров для текста естественного языка, отображаемого пользователями. Подробные рекомендации см. в статье Best practices для сравнения строк в .NET.