util pattern online matches java regex unicode

pattern - regex java 8



Clase de caracteres regex Java no documentados: / p{C} (3)

Encontré una expresión regular interesante en un proyecto de Java: "[//p{C}&&//S]"

Entiendo que && significa "establecer intersección", y /S es "espacios en blanco", pero ¿qué es /p{C} ? ¿Se puede usar?

La documentación de java.util.regex.Pattern no lo menciona. La única clase similar en la lista es /p{Cntrl} , pero se comportan de manera diferente: ambos coinciden en los caracteres de control, pero /p{C} coinciden dos veces en los caracteres Unicode por encima de U + FFFF, como el PILE OF POO :

public class StrangePattern { public static void main(String[] argv) { // As far as I can tell, this is the simplest way to create a String // with code points above U+FFFF. String poo = new String(Character.toChars(0x1F4A9)); System.out.println(poo); // prints `💩` System.out.println(poo.replaceAll("//p{C}", "?")); // prints `??` System.out.println(poo.replaceAll("//p{Cntrl}", "?")); // prints `💩` } }

La única mención que he encontrado en cualquier lugar está here :

/ p {C} o / p {Otros}: caracteres de control invisibles y puntos de código no utilizados.

Sin embargo, /p{Other} no parece existir en Java, y los puntos de código coincidentes no están sin usar.

Mi información de la versión de Java:

$ java -version java version "1.8.0_92" Java(TM) SE Runtime Environment (build 1.8.0_92-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

Pregunta de bonificación : ¿cuál es la intención probable del patrón original, "[//p{C}&&//S]" ? Ocurre en un método que valida una cadena antes de enviarla en un correo electrónico: si ese patrón coincide, se genera una excepción con el mensaje "Cadena no válida".


Cualquier otra cosa que no sea un código de categoría Unicode de dos letras válido o una sola letra que comience con un código de categoría Unicode es ilegal ya que Java solo admite abreviaturas de una letra y de dos letras para las categorías Unicode. Es por eso que /p{Other} no funciona aquí.

/p{C} coincide dos veces en caracteres Unicode por encima de U+FFFF , como PILE OF POO.

Derecha. Java utiliza la codificación UTF-16 internamente para los caracteres Unicode y 💩 se codifica como dos unidades de código de 16 bits ( 0xD83D 0xDCA9 ) llamadas pares sustitutos ( sustitutos altos ) y como /p{C} coincide con cada mitad por separado

/p{Cs} o /p{Surrogate} : la mitad de un par suplente en codificación UTF-16.

Usted ve dos partidos en el conjunto de resultados.

¿Cuál es la intención probable del patrón original, [//p{C}&&//S] ?

No veo una razón válida, pero parece que el desarrollador está preocupado por los personajes de la categoría Other (como evitar los goomojies electrónicos no goomojies en el tema del correo electrónico), así que simplemente intenté bloquearlos.


Enterrado en los documentos de patrón en el soporte de Unicode, encontramos lo siguiente:

Esta clase cumple con el Nivel 1 del Estándar Técnico Unicode # 18: Expresión regular de Unicode , más los equivalentes canónicos de RL2.1.

...

Las categorías se pueden especificar con el prefijo opcional Is: Both / p {L} y / p {IsL} denotan la categoría de las letras Unicode. Igual que los scripts y bloques, las categorías también se pueden especificar utilizando la palabra clave general_category (o su forma corta gc) como en general_category = Lu o gc = Lu.

Las categorías admitidas son las de The Unicode Standard en la versión especificada por la clase de caracteres. Los nombres de las categorías son aquellos definidos en el Estándar, tanto normativos como informativos.

A partir del Estándar Técnico No. 18 de Unicode , encontramos que C está definido para coincidir con cualquier otro valor de Categoría General, y que el soporte para esto es parte de los requisitos para el cumplimiento del Nivel 1. Java implementa /p{C} porque afirma que cumple con el Nivel 1 de UTS # 18.

Probablemente debería soportar /p{Other} , pero aparentemente no lo hace.

Peor aún, es una violación de RL1.7 , requerida para el cumplimiento del Nivel 1, que requiere que la coincidencia ocurra por punto de código en lugar de unidad de código:

Para cumplir con este requisito, una implementación debe manejar el rango completo de puntos de código Unicode, incluidos los valores de U + FFFF a U + 10FFFF. En particular, cuando se usa UTF-16, una secuencia que consiste en un sustituto principal seguido de un sustituto posterior se manejará como un único punto de código en la coincidencia.

No debe haber coincidencias para /p{C} en su cadena de prueba, porque su cadena de prueba debe coincidir como un único punto de código emoji con General_Category = So (Otro símbolo) en lugar de como dos sustitutos.


Según https://regex101.com/ , / p {C} coincide

Caracteres de control invisibles y puntos de código no utilizados.

(/ se debe escapar porque la cadena Java, por lo que la cadena // p {C} es regex / p {C})

Supongo que esto es una ''comprobación de cadena pirateada'' ya que una / p {C} probablemente nunca debería aparecer dentro de una cadena válida (llena de caracteres), pero el autor debería haber dejado un comentario como lo que verificaron y lo que querían verificar Suelen ser 2 cosas diferentes.