J'ai trouvé une expression rationnelle intéressante dans un projet Java: "[\\p{C}&&\\S]"
Je comprends que le &&
signifie "définir l'intersection" et \S
est "non blanc", mais ce qui est \p{C}
, et est-il correct d'utiliser?
La documentation Java.util.regex.Pattern ne le mentionne pas. La seule classe similaire de la liste est \p{Cntrl}
, mais ils se comportent différemment: ils correspondent tous les deux aux caractères de contrôle, mais \p{C}
correspond à deux fois sur les caractères Unicode au-dessus de U + FFFF, tels que 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 seule mention que j'ai trouvée quelque part est ici :
\ p {C} ou\p {Autre}: caractères de contrôle invisibles et points de code inutilisés.
Pourtant, \p{Other}
ne semble pas exister en Java et les points de code correspondants ne sont pas inutilisés.
My Java info version:
$ 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)
Question bonus : quelle est l'intention probable du motif d'origine, "[\\p{C}&&\\S]"
? Il se produit dans une méthode qui valide une chaîne avant son envoi dans un e-mail: si ce modèle est mis en correspondance, une exception avec le message "Chaîne non valide" est déclenchée.
Enfouis dans les documents Pattern sous Support Unicode, nous trouvons ce qui suit:
Cette classe est conforme au niveau 1 de Norme technique Unicode n ° 18: Expression régulière Unicode , plus les équivalents canoniques RL2.1.
...
Les catégories peuvent être spécifiées avec le préfixe facultatif Is:\p {L} et\p {IsL} désignent la catégorie des lettres Unicode. Comme pour les scripts et les blocs, les catégories peuvent également être spécifiées en utilisant le mot-clé general_category (ou sa forme courte gc) comme dans general_category = Lu ou gc = Lu.
Les catégories prises en charge sont celles de la norme Unicode dans la version spécifiée par la classe Character. Les noms de catégorie sont ceux définis dans la norme, à la fois normatifs et informatifs.
D'après Norme technique Unicode # 18 , nous constatons que C
est défini pour correspondre à toute autre valeur General_Category, et que sa prise en charge fait partie des exigences de conformité au niveau 1. Java implémente \p{C}
car il prétend être conforme au niveau 1 de l'UTS # 18.
Il est probablement devrait soutenir \p{Other}
, mais apparemment non.
Pire, cela viole RL1.7 , requis pour la conformité de niveau 1, qui nécessite que la correspondance se fasse par point de code au lieu d'une unité de code:
Pour répondre à cette exigence, une implémentation doit gérer la gamme complète des points de code Unicode, y compris les valeurs de U + FFFF à U + 10FFFF. En particulier, lorsque UTF-16 est utilisé, une séquence composée d'un substitut de tête suivi d'un substitut de fin doit être traitée comme un seul point de code dans la correspondance.
Il ne devrait pas y avoir de correspondance pour \p{C}
dans votre chaîne de test, car votre chaîne de test doit correspondre à un seul point de code emoji avec General_Category = So (Autre symbole) au lieu de deux substituts.
Selon https://regex101.com/ ,\p {C} correspond
Caractères de contrôle invisibles et points de code inutilisés
(le\doit être échappé car Java, donc la chaîne \\ p {C} est regex\p {C})
Je suppose que c'est une "vérification de chaîne piratée" car un\p {C} ne devrait probablement jamais apparaître dans une chaîne valide (remplie de caractères), mais l'auteur aurait dû laisser un commentaire indiquant ce qu'il a vérifié et ce qu'il voulait vérifier sont généralement 2 choses différentes.
Tout ce qui n'est pas un code de catégorie Unicode à deux lettres valide ou une seule lettre qui commence un code de catégorie Unicode est illégal car Java ne prend en charge que les abréviations à une et deux lettres pour les catégories Unicode. C'est pourquoi \p{Other}
ne fonctionne pas ici.
\p{C}
correspond deux fois aux caractères Unicode au-dessus deU+FFFF
, comme PILE OF POO.
Droite. Java utilise le codage UTF-16 en interne pour les caractères Unicode et ???? est codé en deux unités de code 16 bits (0xD83D 0xDCA9
) appelés paires de substitution ( substituts élevés ) et depuis \p{C}
correspond à chaque moitié séparément
\p{Cs}
ou\p{Surrogate}
: la moitié d'une paire de substitution dans le codage UTF-16.
vous voyez deux correspondances dans le jeu de résultats.
Quelle est l'intention probable du modèle d'origine,
[\\p{C}&&\\S]
?
Je ne vois pas de raison valable, mais il semble que le développeur s'inquiète des caractères de la catégorie Other
(comme éviter le spam goomojies
dans le sujet de l'e-mail) alors essayez simplement de bloquer leur.