Regex CUSIP (North American security)
A CUSIP has 9 characters: 6 for the issuer, 2 for the issue and a numeric check digit ('Modulus 10 Double Add Double', close to Luhn). The first eight characters are digits or letters; the special characters '*', '@' and '#' are reserved for the insurance industry's private placement numbers (PPN), according to the Wikipedia article. Among the attempts read, the PHP package DPRMC/CUSIP is unanchored: it recognises 9 characters inside a longer string; the sec_id gem's parser makes the check digit optional; formvalidation's excludes the letters I and O everywhere. Here's an anchored pattern requiring the numeric check digit in last position, compared against those attempts. The check digit is not recomputed.
/^[A-Z0-9*@#]{8}[0-9]$/passes 26/26 cases
Comparison of existing patterns
| Source | pattern | Score on the 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 | safe |
| 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 | safe |
| 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 | safe |
| 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 | safe |
Implementation
const re = new RegExp("^[A-Z0-9*@#]{8}[0-9]$", "");
re.test(input);Limits
- 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.