Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 1316. #ЗаметкиНаПолях Неочевидные Различия в Regex 1. \d или [0-9] В документации .NET про Regex, \d означает любую цифру. Что означает термин «цифра», зависит от опций выражения: - по умолчанию, без опции RegexOptions.ECMAScript, \d означает \p{Nd}, т.е. любой символ из категории «цифр» в Unicode; - с опцией RegexOptions.ECMAScript \d означает [0-9]. Категория цифр в Unicode содержит цифры 0, 1, 2, … но также цифры из других языков, вроде ٣, ٧, ൩ или ໓. Полный список состоит из 610 символов! Поэтому
Regex.IsMatch("०१२३४५६७८९", "[0-9]{10}"); 
вернёт False, тогда как
Regex.IsMatch("०१२३४५६७८९", "\\d{10}");
вернёт True. Добавление опции решает проблему:
Regex.IsMatch("०१२३४५६७८९", "\\d{10}", RegexOptions.ECMAScript);
вернёт False. 2. [a-zA-Z] или [a-z] с IgnoreCase Рассмотрим два регулярных выражения:
var regex1 = new Regex("^[a-zA-Z]+$");
var regex2 = new Regex("^[a-z]+$", 
  RegexOptions.IgnoreCase | 
  RegexOptions.CultureInvariant);

В большинстве случаев они работают одинаково, так, как мы и предполагаем:
regex1.IsMatch("Test"); // True
regex2.IsMatch("Test"); // True

Однако, есть специальный символ K (U+212A), обозначающий температуру по Кельвину, и здесь всё интереснее:
regex1.IsMatch("K"); // False
regex2.IsMatch("K"); // True

Когда в регулярном выражении указан параметр RegexOptions.IgnoreCase, сравнение между входными данными и шаблоном будет выполняться без учёта регистра. Чтобы поддерживать это, Regex необходимо определить, какие отображения регистра будут использоваться для сравнений. Отображение регистра существует всякий раз, когда у вас есть два символа «A» и «B», где либо: - «A» является ToLower() представлением «B», - оба символа являются представлением в нижнем регистре для одного и того же символа. В этом случае char.ToLowerInvariant('K') - это k (строчная латинская буква K). Поэтому второе выражение возвращает True для знака Кельвина, однако он не входит в множество [a-zA-Z], поэтому первое выражение возвращает False. Источник: https://www.meziantou.net/regex-with-ignorecase-option-may-match-more-characters-than-expected.htm