Regex ICD-10-CM code (diagnosis)
An ICD-10-CM code (US diagnosis) has 3 to 7 characters: a letter, a digit, then a digit or 'A' and 'B' ('D3A', 'Z3A'), a dot after the third character, then 1 to 4 alphanumeric characters, e.g. 'E11.9' or 'S72.001A'. The CMS official guidelines say characters may be letters or numbers and that codes have 3, 4, 5, 6 or 7 characters. The attempts I read are either too strict (Wikidata P4229 requires a digit in 3rd position and rejects 'D3A.8'), too loose (identifiers.org accepts 'A1.-'…), or accept block ranges 'E08-E13' (bioregistry). Here's a pattern on the CMS structure, compared against those attempts.
/^[A-Z][0-9][0-9AB](?:\.[0-9A-Z]{1,4})?$/passes 32/32 cases
Comparison of existing patterns
| Source | pattern | Score on the corpus | ReDoS |
|---|---|---|---|
| bioregistry (icd10cm) — jeu de caractères fin par position, très proche du Tabular List ; seule différence relevée sur le corpus : accepte les plages de blocs (« E08-E13 ») | ^([A-Z][0-9][0-9AB]((-[A-Z][0-9][0-9AB])|(\.[0-9A-KXZ]([0-9A-EXYZ]([0-9A-HX][0-59A-HJKMNP-S]?)?)?)?))$ | 31 / 32 | safe |
| Wikidata P4229 (ICD-10-CM) — 3e caractère chiffre obligatoire : « D3A.8 » et « Z3A.01 » refusés ; non ancrée ; accepte les blocs (« E08-E13 ») et toute longueur après le point | [A-Z]\d{2}(-[A-Z]\d{2}|[.][A-Z\d]+|) | 23 / 32 | safe |
| Wikidata P494 (CIM-10 OMS, 1 à 2 décimales) — trop étroite pour ICD-10-CM : lettres après le point et 3e caractère A/B refusés, non ancrée | [A-Z]\d{2}(?:\.\d{1,2})? | 23 / 32 | safe |
| identifiers.org (icd) — « [-\d+] » est une classe : « E11.- » et « E11.+ » passent, un seul caractère après le point, 3e caractère A/B refusé, nombre de chiffres libre | ^[A-Z]\d+(\.[-\d+])?$ | 18 / 32 | safe |
Implementation
const re = new RegExp("^[A-Z][0-9][0-9AB](?:\\.[0-9A-Z]{1,4})?$", "");
re.test(input);Limits
- Valide seulement la FORME ICD-10-CM : un code bien formé peut ne pas exister (« Z99.999Z » passe) ni être facturable (les codes de 3 à 6 caractères peuvent avoir des sous-divisions et seul le dernier niveau est utilisable pour le reporting). L'existence se vérifie dans la liste annuelle du CDC/CMS ou une API (NLM Clinical Tables).
- Ne vaut pas pour la CIM-10 de l'OMS (sans « U » étendu ni 7e caractère) ni pour ICD-10-PCS (7 caractères sans point) ni pour la CIM-11. La forme sans point (« E119 »), utilisée en facturation, est refusée : ajoutez ou retirez le point avant validation.
- Les minuscules sont refusées (les lignes directrices ne disent pas que la casse compte : normalisez en majuscules). Les plages de blocs (« E08-E13 ») ne sont pas des codes et sont refusées.