Regex CUIT argentin (identifiant fiscal)
Un CUIT (ou CUIL) a 11 chiffres, écrits « 20-05536168-2 » : un préfixe de 2 chiffres, 8 chiffres (le numéro de DNI ou de société, complété par un zéro si besoin) et une clé calculée en modulo 11 avec les poids 5 4 3 2 7 6 5 4 3 2. Les préfixes courants sont 20, 23, 24 et 27 pour les personnes physiques, 30, 33 et 34 pour les sociétés. Les trois motifs relus ici ne contrôlent pas tous le préfixe : validator.js le fait mais sans ancres ni tirets, django-localflavor et afip-cuit-validator acceptent n'importe quels deux chiffres. Voici un motif ancré qui borne le préfixe et impose le même choix (avec ou sans tirets) aux deux séparateurs, comparé à ces tentatives.
/^(?:20|23|24|27|30|33|34)(-?)[0-9]{8}\1[0-9]$/passe 24/24 cas
Comparatif des patterns existants
| Source | pattern | Score sur le corpus | ReDoS |
|---|---|---|---|
| validator.js isTaxID('es-AR') — préfixe contrôlé mais aucune ancre : « X20055361682Y » passe, et les tirets ne sont pas gérés (« 20-05536168-2 » refusé) | (20|23|24|27|30|33|34)[0-9]{8}[0-9] | 16 / 24 | sûr |
| django-localflavor (ar/forms.py) — n'importe quel préfixe (« 99-05536168-2 » passe), tirets indépendants (« 20-055361682 » passe) ; le type est contrôlé ensuite dans le code | ^\d{2}-?\d{8}-?\d$ | 20 / 24 | sûr |
| afip-cuit-validator (npm) — deux regex en OU : n'importe quel préfixe, et la forme avec tirets doit être complète ; « 99-05536168-2 » et « 99055361682 » passent | ^\d{2}\-\d{8}\-\d{1}$|^\d{11}$ | 22 / 24 | sûr |
Implémentation
const re = new RegExp("^(?:20|23|24|27|30|33|34)(-?)[0-9]{8}\\1[0-9]$", "");
re.test(input);Limites
- Valide seulement la FORME : ne calcule pas la clé modulo 11. « 20-05536168-3 » a la bonne forme mais une clé fausse et passe ce motif. Ni l'existence du contribuable, ni la cohérence avec le DNI ne sont contrôlées.
- Les préfixes ne font pas consensus : Wikipédia cite aussi 25 et 26, python-stdnum accepte 50, 51 et 55 (usages internationaux). Le motif ne retient que les sept préfixes communs aux implémentations lues ; ajoutez les autres si votre cas l'exige.
- Quand le calcul donne 10, la clé n'est pas attribuée telle quelle (le préfixe est alors remplacé, d'après Wikipédia) ; validator.js et python-stdnum, eux, convertissent 10 en 9. Aucune regex ne peut tester cela.
- Le CUIT d'une personne physique contient son numéro de DNI : c'est une donnée personnelle. N'utilisez que des exemples de documentation ou synthétiques, comme ceux du corpus.