Use expressões regulares para combinar com QUALQUER caractere chinês na codificação utf-8

Por exemplo, eu quero corresponder uma string que consiste em m para n caracteres chineses, então eu posso usar:

 [single Chinese character regular expression]{m,n} 

Existe alguma expressão regular de um único caractere chinês, que poderia ser qualquer caractere chinês que existe?

O regex para corresponder a um caractere chinês (bem, CJK) é

 \p{script=Han} 

que pode ser considerado simplesmente

 \p{Han} 

Isso pressupõe que seu compilador regex atenda às propriedades RL1.2 de requisito das expressões regulares Unicode UTS # 18 . Tanto o Perl quanto o Java 7 atendem a essa especificação, mas muitos outros não.

Em Java,

 \p{InCJK_UNIFIED_IDEOGRAPHS}{1,3} 

Existe alguma expressão regular de um único caractere chinês, que poderia ser qualquer caractere chinês que existe?

Recomendação

Para combinar padrões com caracteres chineses e outros pontos de código Unicode com um analisador léxico compatível com Flex, você poderia usar o analisador léxico RE / flex para C ++ que é compatível com versões anteriores do Flex. O RE / flex suporta o Unicode e trabalha com o Bison para construir lexers e analisadores.

Você pode escrever padrões Unicode (e expressões regulares UTF-8) em especificações RE / flex como:

 %option flex unicode %% [肖晗] { printf ("xiaohan/2\n"); } %% 

Use a %option unicode global %option unicode para ativar o Unicode. Você também pode usar um modificador local (?u:) para restringir Unicode a um único padrão (para que todo o resto ainda seja ASCII / 8-bit como no 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]); } %% 

A opção flex permite compatibilidade com Flex, portanto, você pode usar yytext , yyleng , ECHO e assim por diante. Sem a opção flex RE / flex espera chamadas do método Lexer: text() (ou str() e wstr() para std::string e std::wstring ), size() (ou wsize() para largura larga) e echo() . Chamadas de método RE / flex são IMHO mais limpas e incluem operações de caracteres largas.

fundo

No antigo e simples Flex, acabei definindo padrões UTF-8 feios para capturar letras ASCII e letras codificadas em UTF-8 para um projeto de compilador que exigia suporte para identificadores de identificadores Unicode:

 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})* 

O padrão alpha suporta letras ASCII, sublinhado e pontos de código Unicode usados ​​em identificadores ( \p{L} etc). O padrão permite mais pontos de código Unicode do que o absolutamente necessário para manter o tamanho desse padrão gerenciável, de modo que ele compara a compactação por alguma falta de precisão e permite caracteres UTF-8 muito longos em alguns casos que não são UTF-8 válidos. Se você está pensando sobre esta abordagem, tenha cuidado com os problemas e preocupações de segurança. Use um gerador de scanner compatível com Unicode, como RE / flex .

Segurança

Ao usar o UTF-8 diretamente nos padrões Flex, existem várias preocupações:

  1. Codificar seus próprios padrões UTF-8 no Flex para correspondência de qualquer caractere Unicode pode ser propenso a erros. Padrões devem ser restritos a caracteres somente no intervalo Unicode válido. Pontos de código Unicode cobrem o intervalo U + 0000 para U + D7FF e U + E000 para U + 10FFFF. O intervalo U + D800 a U + DFFF é reservado para pares substitutos UTF-16 e são pontos de código inválidos . Ao usar uma ferramenta para converter um intervalo Unicode em UTF-8, exclua os pontos de código inválidos.

  2. Os padrões devem rejeitar as sequências de bytes inválidos e demais. UTF-8 inválido não deve ser aceito silenciosamente.

  3. Para capturar erros de input lexical no seu lexer vai exigir um especial . (ponto) que corresponde a Unicode válido e inválido, incluindo overruns UTF-8 e seqüências de bytes inválidos, para produzir uma mensagem de erro informando que a input foi rejeitada. Se você usar ponto como um “catch-all-else” para produzir uma mensagem de erro, mas seu ponto não corresponder a Unicode inválido, o lexer será interrompido (“scanner está preso”) ou o seu lexer irá exibir caracteres de lixo na saída pela “regra padrão” do Flex.

  4. Seu scanner deve reconhecer uma BOM UTF (Unicode Byte Order Mark) na input para alternar para UTF-8, UTF-16 (LE ou BE) ou UTF-32 (LE ou BE).

  5. Como você aponta, padrões como [unicode characters] não funcionam com o Flex, porque os caracteres UTF-8 em uma lista de colchetes são caracteres de vários bytes e cada caractere de byte único pode ser correspondido, mas não o caractere UTF-8.

Veja também codificações UTF inválidas no guia do usuário do RE / flex.

No Java 7 e acima, o formato deve ser: “\ p {IsHan}”

    Intereting Posts