Regex CUSIP (titre nord-américain)
Un CUSIP compte 9 caractères : 6 pour l'émetteur, 2 pour l'émission et une clé de contrôle chiffrée (méthode « Modulus 10 Double Add Double », proche de Luhn). Les huit premiers caractères sont des chiffres ou des lettres ; les caractères spéciaux « * », « @ » et « # » sont réservés aux numéros de placement privé (PPN) du secteur de l'assurance, d'après l'article Wikipédia. Parmi les tentatives relues, celle du paquet PHP DPRMC/CUSIP n'est pas ancrée : elle reconnaît 9 caractères dans une chaîne plus longue ; l'analyseur du gem sec_id rend la clé facultative ; celle de formvalidation exclut les lettres I et O partout. Voici un motif ancré qui exige la clé numérique en dernière position, comparé à ces tentatives. La clé n'est pas recalculée.
/^[A-Z0-9*@#]{8}[0-9]$/Comparatif des patterns existants
| Source | pattern | Score sur le corpus | ReDoS |
|---|---|---|---|
| DPRMC/CUSIP (PHP) — REGEX_PATTERN non ancrée : « xx037833100xx » passe, tout bloc de 9 caractères dans un texte plus long, y compris 9 lettres ; ne distingue pas la clé numérique | [\dA-Z@\*\#]{9} | 20 / 26 | sûr |
| sec_id (gem Ruby, ID_REGEX du CUSIP, mode /x condensé) — clé finale facultative : un identifiant de 8 caractères passe ; les 5 premiers caractères excluent *, @ et # (« AB12#@*90 » est refusé) | ^[A-Z0-9]{5}[A-Z0-9*@#][A-Z0-9*@#]{2}\d?$ | 23 / 26 | sûr |
| formvalidation (@form-validation/validator-cusip 2.4.0) — exclut I et O dans tous les rangs (« I12345678 » est refusé) et accepte une lettre en dernière position (« 03783310A ») | ^[0123456789ABCDEFGHJKLMNPQRSTUVWXYZ*@#]{9}$ | 25 / 26 | sûr |
| Rosetta Code (Factor, test de forme du mot cusip?, R/ [0-9A-Z*@#]+/ matches?, ancres ajoutées) : n'importe quelle longueur, la clé n'est contrôlée qu'ensuite par le calcul | ^[0-9A-Z*@#]+$ | 22 / 26 | sûr |
Implémentation
const re = new RegExp("^[A-Z0-9*@#]{8}[0-9]$", "");
re.test(input);Limites
- Valide seulement la FORME : « 68389X106 » a la bonne structure mais une clé fausse (la bonne valeur est 5) et passe ce motif. La clé « Modulus 10 Double Add Double » n'est pas recalculée par la regex.
- N'établit pas qu'un titre existe : seul le registre de CUSIP Global Services le confirme. Un CUSIP est une donnée propriétaire dont la redistribution est encadrée.
- Les caractères spéciaux * @ # sont acceptés dans les 8 premiers rangs sans vérifier qu'il s'agit d'un PPN ; la position réelle n'est pas précisée dans les sources lues. Les lettres I et O sont acceptées : l'article Wikipédia ne les exclut que dans les libellés d'émission obligataires, formvalidation les exclut partout.
- Un CUSIP de 9 caractères ne doit pas être confondu avec un CINS (qui commence par une lettre) ni avec un ISIN américain (US + CUSIP + clé ISIN) : voir la fiche isin. Aucune tolérance pour espaces, tirets ou minuscules.