Regex MMSI identifier
An MMSI isn't just "9 digits": its structure changes depending on the station type - a ship starts directly with its country code (MID, 201-775), a coast station with two zeros, a search-and-rescue aircraft with "111". The mmsi.js JS library only checks the length, while the open Signal K standard (used in marine electronics) only covers the "ship" format and wrongly rejects every other legitimate category. Here's a pattern covering all six standardized structures, compared against these three attempts.
/^(?:(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\d{6}|0(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\d{5}|00(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\d{4}|111(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\d{3}|8(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\d{5}|9[89](?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\d{4})$/passes 22/22 cases
Comparison of existing patterns
| Source | pattern | Score on the corpus | ReDoS |
|---|---|---|---|
| mikeu/mmsi.js (bibliothèque JS de parsing MMSI) — ne vérifie que le nombre de chiffres, accepte n'importe quel MID hors de la plage 201-775 | ^[0-9]{9}$ | 18 / 22 | safe |
| Signal K specification (norme ouverte d'électronique marine) — ne couvre que le format « navire », rejette à tort les stations côtières, aéronefs SAR et autres catégories légitimes | ^[2-7][0-9]{8}$ | 17 / 22 | safe |
| regex101.com (auteur Shay Nissel, se réclamant conforme à la doc USCG) — répète 5 fois le même sous-motif de plage MID et code en dur les préfixes DOM français comme alternatives littérales | ^((((2(0[1-9]|[1-9][0-9]))|([3-6][0-9]{2})|(7([0-6][0-9]|7[0-5])))[0-9]{6})|((0|8)((2(0[1-9]|[1-9][0-9]))|([3-6][0-9]{2})|(7([0-6][0-9]|7[0-5])))[0-9]{5})|((00|99|98)((2(0[1-9]|[1-9][0-9]))|([3-6][0-9]{2})|(7([0-6][0-9]|7[0-5])))[0-9]{4})|(111((2(0[1-9]|[1-9][0-9]))|([3-6][0-9]{2})|(7([0-6][0-9]|7[0-5])))[0-9]{3})|((970|972|974)[0-9]{6}))$ | 21 / 22 | safe |
Implementation
const re = new RegExp("^(?:(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\\d{6}|0(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\\d{5}|00(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\\d{4}|111(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\\d{3}|8(?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\\d{5}|9[89](?:2(?:0[1-9]|[1-9][0-9])|[3-6][0-9]{2}|7(?:[0-6][0-9]|7[0-5]))\\d{4})$", "");
re.test(input);Limits
- Valide seulement la STRUCTURE (préfixe par catégorie + plage de MID 201-775) : ne consulte aucun registre d'attribution réel — un MMSI syntaxiquement valide selon ce motif peut n'avoir jamais été attribué à un navire ou une station existants.
- Ne couvre pas les séries spéciales non liées à un pays : les identifiants d'appareils de recherche et sauvetage (SART, préfixe 970), de dispositifs homme à la mer (MOB, préfixe 972) et de balises EPIRB-AIS (préfixe 974) suivent une structure différente, hors périmètre de ce motif.
- N'impose pas les contraintes fines documentées sur certains chiffres de remplissage (ex. le 7ᵉ chiffre d'un aéronef SAR distingue voilure fixe et hélicoptère) : ce motif valide la structure générale, pas chaque chiffre à signification propre.
- Exige une chaîne de 9 chiffres consécutifs sans séparateur : les espaces parfois utilisés à l'affichage doivent être retirés avant validation.