C # Регулярные выражения с символами \ Uxxxxxxxx в шаблоне - PullRequest
6 голосов
/ 12 декабря 2008
Regex.IsMatch( "foo", "[\U00010000-\U0010FFFF]" ) 

Выдает: System.ArgumentException: анализ диапазона «[-]» - [x-y] в обратном порядке.

Глядя на шестнадцатеричные значения для \ U00010000 и \ U0010FFF, я получаю: 0xd800 0xdc00 для первого символа и 0xdbff 0xdfff для второго.

Так что, думаю, у меня действительно есть одна проблема. Почему символы Юникода, образованные с \ U, разделяются на две буквы в строке?

Ответы [ 3 ]

10 голосов
/ 12 декабря 2008

Это суррогатные пары . Посмотрите на значения - они превышают 65535. Символ - это только 16-битное значение. Как бы вы выразили 65536 только в 16 битах?

К сожалению, из документации не ясно, как (или действительно ли) механизм регулярных выражений в .NET справляется с символами, которые не находятся в основной многоязычной плоскости. (Шаблон \ uxxxx в документации по регулярным выражениям охватывает только 0-65535, точно так же, как \ uxxxx как escape-последовательность C #.)

Ваше реальное регулярное выражение больше или вы просто пытаетесь увидеть, есть ли здесь какие-нибудь не-BMP символы?

4 голосов
/ 15 января 2013

Чтобы обойти такие вещи с помощью движка .Net regex, я использую следующую хитрость: "[\U010000-\U10FFFF]" заменяется на [\uD800-\uDBFF][\uDC00-\uDFFF] Идея заключается в том, что поскольку регулярные выражения .Net обрабатывают кодовые единицы вместо кодовых точек, мы предоставляем ему суррогатные диапазоны в виде обычных символов. Также можно указать более узкие диапазоны, работая с ребрами, например: [\U011DEF-\U013E07] совпадает с (?:\uD807[\uDDEF-\uDFFF])|(?:[\uD808-\uD80E][\uDC00-\uDFFF])|(?:\uD80F[\uDC00-uDE07])

С ним труднее читать и работать, и он не настолько гибок, но все же подходит в качестве обходного пути.

1 голос
/ 12 декабря 2008

@ Джон Скит

Итак, вы говорите мне, что нет способа использовать инструменты Regex в .net для сопоставления с символами вне диапазона utf-16?

Полное регулярное выражение:

^(\u0009|[\u0020-\u007E]|\u0085|[\u00A0-\uD7FF]|[\uE000-\uFFFD]|[\U00010000-\U0010FFFF])+$

Я пытаюсь проверить, содержит ли строка только то, что документ yaml определяет как печатаемые символы Юникода.

...