Используйте регулярное выражение для сопоставления ЛЮБОГО китайского символа в кодировке utf-8
Например, я хочу сопоставить строку, состоящую из m
в n
Китайские иероглифы, тогда я могу использовать:
[single Chinese character regular expression]{m,n}
Существует ли какое-либо регулярное выражение одного китайского символа, который может быть любым существующим китайским символом?
8 ответов
Регулярное выражение для соответствия китайскому (ну, CJK) символу
\p{script=Han}
который может быть назначен просто
\p{Han}
Это предполагает, что ваш компилятор регулярных выражений соответствует требованию RL1.2 Свойства из регулярных выражений Unicode UTS#18. Perl и Java 7 оба соответствуют этой спецификации, но многие другие не соответствуют.
В C#
new Regex(@"\p{IsCJKUnifiedIdeographs}")
Вот это в документах Microsoft
А вот дополнительная информация из Википедии: Единые идеограммы CJK
Базовый блок под названием CJK Unified Ideographs (4E00–9FFF) содержит 20976 основных китайских символов в диапазоне от U+4E00 до U+9FEF. В блок входят не только символы, используемые в китайской системе письма, но также иероглифы, используемые в японской системе письма, и ханджа, использование которых в Корее сокращается. Многие символы в этом блоке используются во всех трех системах письма, а другие - только в одной или двух из трех. Китайские иероглифы также используются во вьетнамском письме Ном (ныне устаревшем).
Существует ли какое-либо регулярное выражение одного китайского символа, который может быть любым существующим китайским символом?
Рекомендация
Чтобы сопоставлять шаблоны с китайскими символами и другими кодовыми точками Юникода с помощью Flex-совместимого лексического анализатора, вы можете использовать лексический анализатор RE/flex для C++, который обратно совместим с Flex. RE/flex поддерживает Unicode и работает с Bison для создания лексеров и парсеров.
Вы можете написать шаблоны Unicode (и регулярные выражения UTF-8) в спецификациях RE/flex, таких как:
%option flex unicode
%%
[肖晗] { printf ("xiaohan/2\n"); }
%%
Используйте глобальный %option unicode
включить Юникод. Вы также можете использовать локальный модификатор (?u:)
чтобы ограничить Unicode одним шаблоном (так что все остальное по-прежнему ASCII/8-битное, как в Flex):
%option flex
%%
(?u:[肖晗]) { printf ("xiaohan/2\n"); }
(?u:\p{Han}) { printf ("Han character %s\n", yytext); }
. { printf ("8-bit character %d\n", yytext[0]); }
%%
вариант flex
обеспечивает совместимость с Flex, поэтому вы можете использовать yytext
, yyleng
, ECHO
, и так далее. Без flex
опция RE/flex ожидает вызова метода Lexer: text()
(или же str()
а также wstr()
за std::string
а также std::wstring
), size()
(или же wsize()
для большой длины символа) и echo()
, Вызовы методов RE/flex более чистые ИМХО и включают в себя операции с широкими символами.
Фон
В простом старом Flex я в конечном итоге определил некрасивые шаблоны UTF-8 для захвата букв ASCII и букв в кодировке UTF-8 для проекта компилятора, который требовал поддержки идентификаторов Unicode id
:
digit [0-9]
alpha ([a-zA-Z_\xA8\xAA\xAD\xAF\xB2\xB5\xB7\xB8\xB9\xBA\xBC\xBD\xBE]|[\xC0-\xFF][\x80-\xBF]*|\\u([0-9a-fA-F]{4}))
id ({alpha})({alpha}|{digit})*
alpha
шаблон поддерживает буквы ASCII, символы подчеркивания и кодовые точки Unicode, которые используются в идентификаторах (\p{L}
так далее). Шаблон допускает больше кодовых точек Unicode, чем абсолютно необходимо, чтобы поддерживать размер этого шаблона управляемым, поэтому он торгует компактностью за некоторую нехватку точности и разрешает использование длинных символов UTF-8 в некоторых случаях, которые не являются допустимыми UTF-8. Если вы думаете об этом подходе, будьте осторожны с проблемами и проблемами безопасности. Вместо этого используйте генератор сканера с поддержкой Unicode, например RE/flex.
безопасности
При использовании UTF-8 непосредственно в шаблонах Flex существует несколько проблем:
Кодирование ваших собственных шаблонов UTF-8 во Flex для сопоставления с любым символом Unicode может привести к ошибкам. Шаблоны должны быть ограничены символами только в допустимом диапазоне Юникода. Кодовые точки Unicode охватывают диапазон от U+0000 до U+D7FF и от U+E000 до U+10FFFF. Диапазон от U+D800 до U+DFFF зарезервирован для суррогатных пар UTF-16 и является недействительными кодовыми точками. При использовании инструмента для преобразования диапазона Unicode в UTF-8 обязательно исключайте недопустимые кодовые точки.
Шаблоны должны отклонять слишком длинные и другие недопустимые последовательности байтов. Неверный UTF-8 не должен приниматься в молчании.
Для отлова лексических ошибок ввода в вашем лексере потребуется специальный
.
(точка), которая соответствует действительному и недействительному Unicode, включая переполнения UTF-8 и недопустимые последовательности байтов, чтобы выдать сообщение об ошибке, что ввод отклонен. Если вы используете точку в качестве "поймать все остальное" для создания сообщения об ошибке, но ваша точка не соответствует недействительному Unicode, то вы повредите лексер ("сканер замят") или ваш лексер будет выводить мусорные символы ECHO на выходе по Flex "правило по умолчанию".Ваш сканер должен распознавать UTF BOM (метку порядка байтов Unicode) на входе, чтобы переключиться на UTF-8, UTF-16 (LE или BE) или UTF-32 (LE или BE).
Как вы указали, такие шаблоны, как
[unicode characters]
с Flex не работают вообще, потому что символы UTF-8 в списке в скобках являются многобайтовыми символами, и каждый однобайтовый символ может совпадать, но не символ UTF-8.
См. Также недопустимые кодировки UTF в руководстве пользователя RE/flex.
Для большинства языков программирования регулярное выражение, соответствующее более чем 99,9% китайских символов, будет:
\u4E00-\u9FFF
Работает с: Python, современным Javascript, Golang, Rust, но не с PHP.
Полезно, если ваш язык не поддерживает такие обозначения, как{Han}
/{script=Han}
/{IsCJKUnifiedIdeographs}
в других ответах.
Примечание. Это соответствует унифицированным иероглифам CJK и включает в себя другие языки, такие как корейский, японский и вьетнамский.
Только что решил аналогичную проблему,
когда у вас слишком много вещей, чтобы соответствовать, лучше использовать
negated-set
и объявите, что вы не хотите сопоставлять, например:
все, кроме чисел:
^[^0-9]*$
второй
^
будет реализовывать отрицание
именно так:
package main
import (
"fmt"
"regexp"
)
func main() {
compile, err := regexp.Compile("\\p{Han}") // match one any Chinese character
if err != nil {
return
}
str := compile.FindString("hello 世界")
fmt.Println(str) // output: 世
}