День 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