Regex.IsMatch( "foo", "[\U00010000-\U0010FFFF]" )
Выдает: System.ArgumentException: анализ диапазона «[-]» - [x-y] в обратном порядке.
Глядя на шестнадцатеричные значения для \ U00010000 и \ U0010FFF, я получаю: 0xd800 0xdc00 для первого символа и 0xdbff 0xdfff для второго.
Так что, наверное, у меня действительно есть одна проблема. Почему символы Юникода, образованные с помощью \ U, разделены на два символа в строке?





Это суррогатные пары. Посмотрите на значения - они больше 65535. Символ - это всего лишь 16-битное значение. Как бы вы выразили 65536 всего лишь в 16 битах?
К сожалению, из документации не ясно, как (и справляется ли) механизм регулярных выражений в .NET с символами, которые не находятся в базовой многоязычной плоскости. (Шаблон \ uxxxx в документации по регулярным выражениям охватывает только 0-65535, точно так же, как \ uxxxx как escape-последовательность C#.)
Ваше реальное регулярное выражение больше или вы просто пытаетесь увидеть, есть ли в нем символы, отличные от BMP?
Без @ вам нужно было бы экранировать \ if \ UFFFF был синтаксисом регулярного выражения (например, \ d для [0-9]), но вместо этого это синтаксис строкового литерала (например, \ n для символа новой строки).
Это прискорбно - многие современные смайлы попадают в эту категорию.
@damian: Вполне возможно, что за 7 лет, прошедших после этого поста, движок регулярных выражений стал лучше в этом отношении. Обратите внимание, что вопрос, на который я отвечал, касался только того, почему \Uxxxxxxxx заканчивается двумя символами ... часть "обработка регулярного выражения" несколько отделена. Возможно, вы захотите задать новый вопрос, если столкнетесь с этим в данный момент.
12 лет с момента публикации, и это все еще не поддерживается.
@Jon Skeet
Итак, вы говорите мне, что нет способа использовать инструменты Regex в .net для сопоставления с символами за пределами диапазона utf-16?
Полное регулярное выражение:
^(\u0009|[\u0020-\u007E]|\u0085|[\u00A0-\uD7FF]|[\uE000-\uFFFD]|[\U00010000-\U0010FFFF])+$
Я пытаюсь проверить, содержит ли строка только то, что документ yaml определяет как печатные символы Unicode.
К сожалению, не знаю. Я не вижу в документации ничего о том, как использовать механизм регулярных выражений .NET с символами за пределами базовой многоязычной плоскости. Однако, вероятно, не так уж сложно реализовать то, что вы хотите, вообще без использования регулярных выражений.
В качестве альтернативы вы можете использовать 16-битные кодовые точки, составляющие суррогатные пары: [\ ud800– \ udfff]. По крайней мере, это стоит попробовать ...
(И в этот момент вы можете объединить несколько своих диапазонов вместе - более поздние биты просто [\ u00a0- \ ufffd].)
Механизм регулярных выражений .NET работает с кодовыми точками UTF-16, а не с символами Unicode; см. code.logos.com/blog/2008/07/…. Я зарегистрировал ошибку Connect по этой проблеме: connect.microsoft.com/VisualStudio/feedback/…
Чтобы обойти такие вещи с помощью механизма регулярных выражений .Net, я использую следующий трюк:
"[\U010000-\U10FFFF]" заменен на [\uD800-\uDBFF][\uDC00-\uDFFF]
Идея заключается в том, что поскольку регулярные выражения .Net обрабатывают единицы кода, а не точки кода, мы предоставляем им суррогатные диапазоны как обычные символы. Также можно указать более узкие диапазоны, работая с краями, например: [\U011DEF-\U013E07] такой же, как (?:\uD807[\uDDEF-\uDFFF])|(?:[\uD808-\uD80E][\uDC00-\uDFFF])|(?:\uD80F[\uDC00-uDE07])
С ним труднее читать и работать, и он не такой гибкий, но все же подходит в качестве временного решения.
Собственно, ты прав. Из того, что я нашел, \ u поддерживает только 4 шестнадцатеричных цифры (ровно 4, не больше и не меньше), \ uFFFF - максимум. Я удалил свое «решение», потому что, хотя оно не вызывает ошибки, оно не похоже на правильное регулярное выражение Юникода. Я все еще считаю, что \ нужно избегать.