Regex arXiv identifier
arXiv documents two schemes. Since April 2007: YYMM.NNNN (4 digits until December 2014) then YYMM.NNNNN (5 digits since January 2015). Before that: archive[.CL]/YYMMNNN (3 sequence digits, July 1991 to March 2007). A 'vN' version may follow. The attempts I read are either too loose (bioregistry's pattern accepts a bare '1234', Wikidata's expression leaves an unescaped dot and is unanchored) or limited to one scheme (the arxiv-base repository's ones handle one scheme each and accept '0000.0000' or month 00). Here's a pattern tying the digit count to the period, compared against those attempts.
/^(?:(?:07(?:0[4-9]|1[0-2])|(?:0[89]|1[0-4])(?:0[1-9]|1[0-2]))\.[0-9]{4}|(?:1[5-9]|[2-9][0-9])(?:0[1-9]|1[0-2])\.[0-9]{5}|[a-z]+(?:-[a-z]+)?(?:\.[A-Za-z-]{2,})?/(?:91(?:0[7-9]|1[0-2])|(?:9[2-9]|0[0-6])(?:0[1-9]|1[0-2])|070[1-3])[0-9]{3})(?:v[1-9][0-9]*)?$/passes 32/32 cases
Comparison of existing patterns
| Source | pattern | Score on the corpus | ReDoS |
|---|---|---|---|
| Wikidata P818 — non ancrée, point non échappé (« 1706x03762 » passe), mois et nombre de chiffres non bornés | (\d{4}.\d{4,5}|[a-z\-]+(\.[A-Z]{2})?\/\d{7})(v\d+)? | 19 / 32 | vulnerable (------------------------------------------------------------…) |
| bioregistry / identifiers.org — très lâche : « 1234 » ou « abc1234 » passent, mois et période non contrôlés | ^(\w+(\-\w+)?(\.\w+)?\/?)?\d{4,7}(\.\d+(v\d+)?)?$ | 17 / 32 | safe |
| arxiv-base RE_ARXIV_NEW_ID — nouveau schéma seulement ; mois 00 et 4/5 chiffres non liés à la date ; accepte un suffixe « #… » ou « /… » | ^(?<yymm>(?<yy>\d\d)(?<mm>\d\d))\.(?<num>\d{4,5})(v(?<version>[1-9]\d*))?(?<extra>[#\/].*)?$ | 20 / 32 | safe |
| arxiv-base RE_ARXIV_OLD_ID — ancien schéma seulement ; mois et période non bornés ; accepte un suffixe « #… » ou « /… » | ^(?<archive>[a-z]{1,}(\-[a-z]{2,})?)(\.([a-zA-Z\-]{2,}))?\/(?<yymm>(?<yy>\d\d)(?<mm>\d\d))(?<num>\d\d\d)(v(?<version>[1-9]\d*))?(?<extra>[#\/].*)?$ | 23 / 32 | safe |
Implementation
const re = new RegExp("^(?:(?:07(?:0[4-9]|1[0-2])|(?:0[89]|1[0-4])(?:0[1-9]|1[0-2]))\\.[0-9]{4}|(?:1[5-9]|[2-9][0-9])(?:0[1-9]|1[0-2])\\.[0-9]{5}|[a-z]+(?:-[a-z]+)?(?:\\.[A-Za-z-]{2,})?/(?:91(?:0[7-9]|1[0-2])|(?:9[2-9]|0[0-6])(?:0[1-9]|1[0-2])|070[1-3])[0-9]{3})(?:v[1-9][0-9]*)?$", "");
re.test(input);Limits
- Valide seulement la FORME et la période (4 chiffres de 0704 à 1412, 5 chiffres depuis 1501) : ni l'existence du preprint ni le numéro de séquence maximal du mois ne sont vérifiés. Le préfixe « arXiv: » et les URL sont refusés : normalisez avant.
- Pour l'ancien schéma, le motif accepte toute archive de lettres minuscules (avec un tiret) et toute classe thématique de lettres ou tirets ; il ne connaît pas la liste des archives (celle d'arxiv-base). Les suffixes de page « #… » sont refusés.
- La borne haute de l'année n'est pas contrôlée au-delà de 99 (le schéma officiel parle de 2099, voire 2106).