Regex PAN indien (numéro de compte permanent)
Le PAN (Permanent Account Number) délivré par l'administration fiscale indienne a 10 caractères : cinq lettres, quatre chiffres, une lettre. La FAQ de l'administration (TRACES) précise que le 4e caractère donne le type de titulaire, parmi A B C F G H J L P T, et que le 5e est l'initiale du nom de famille (ou du nom de l'entité). python-stdnum et validator.js écartent en plus la série « 0000 », une règle absente de la FAQ. Les motifs relus ici ont chacun un défaut : django-localflavor accepte la série 0000, python-stdnum ne contrôle le 4e caractère qu'après la regex, et Presidio, conçu pour détecter, n'est pas ancré. Voici un motif ancré qui contrôle le type et la série, comparé à ces tentatives.
/^[A-Z]{3}[ABCFGHJLPT][A-Z](?!0000)[0-9]{4}[A-Z]$/passe 22/22 cas
Comparatif des patterns existants
| Source | pattern | Score sur le corpus | ReDoS |
|---|---|---|---|
| validator.js isTaxID('en-IN') — ancrée, type de titulaire et série 0000 contrôlés : équivalente au motif recommandé, sans défaut constaté sur ce corpus | ^[A-Z]{3}[ABCFGHLJPT][A-Z](?!0000)[0-9]{4}[A-Z]$ | 22 / 22 | sûr |
| django-localflavor (in_/forms.py) — type de titulaire contrôlé mais la série « 0000 » passe | ^[A-Z]{3}[ABCFGHLJPT][A-Z][0-9]{4}[A-Z]$ | 21 / 22 | sûr |
| python-stdnum (in_/pan.py) — le 4e caractère n'est pas contrôlé par la regex (« ABCDE1234F » passe ; le module le vérifie ensuite) et la série 0000 passe | ^[A-Z]{5}[0-9]{4}[A-Z]$ | 18 / 22 | sûr |
| Presidio, motif « PAN (High) » — détection par \b, non ancrée : « id:ABCPA1234D » et une version en minuscules passent, série 0000 acceptée | \b([A-Za-z]{3}[AaBbCcFfGgHhJjLlPpTt]{1}[A-Za-z]{1}[0-9]{4}[A-Za-z]{1})\b | 18 / 22 | sûr |
Implémentation
const re = new RegExp("^[A-Z]{3}[ABCFGHJLPT][A-Z](?!0000)[0-9]{4}[A-Z]$", "");
re.test(input);Limites
- Valide seulement la FORME : la lettre finale suit un algorithme non publié, aucune regex ne peut la contrôler, et le 5e caractère (initiale du nom) ne peut pas être vérifié sans le nom.
- La règle « série différente de 0000 » vient de python-stdnum et de validator.js, pas de la FAQ de l'administration, qui ne dit que « quatre chiffres ». Si vous voulez coller strictement à la FAQ, retirez le « (?!0000) ».
- Les lettres majuscules seulement : normalisez la casse avant. Le type « K » (accepté par certaines bibliothèques) est refusé car absent de la liste de la FAQ.
- N'établit pas qu'un PAN a été attribué (la vérification se fait auprès de l'administration). Les PAN du corpus n'ont aucune clé publique : un exemple synthétique peut coïncider avec un vrai numéro, ne les utilisez que comme données de test.