La regex suivante
var patt1=/[0-9a-z]+$/i;
extrait l'extension de fichier de chaînes telles que
filename-jpg
filename#gif
filename.png
Comment modifier cette expression régulière pour ne renvoyer une extension que lorsque string est vraiment un nom de fichier avec un point comme séparateur? (Évidemment, le nom de fichier # gif n'est pas un nom de fichier normal)
UPDATE Sur la base des commentaires de tvanofsson, je voudrais préciser que lorsque la fonction JS recevra la chaîne, celle-ci contiendra déjà un nom de fichier sans espaces, sans les points et les autres caractères spéciaux (elle sera en réalité traitée par slug
). Le problème n'était pas dans l'analyse des noms de fichiers mais dans l'analyse incorrecte des slugs - la fonction renvoyait une extension "jpg" lorsqu'elle recevait "filename-jpg" alors qu'elle devrait vraiment renvoyer null
ou une chaîne vide et c'est ce comportement qui devait être corrigée.
Ajoutez simplement un .
à l'expression régulière
var patt1=/\.[0-9a-z]+$/i;
Comme le point est un caractère spécial dans regex, vous devez l'échapper pour le faire correspondre à la lettre: \.
.
Votre modèle correspondra maintenant à toute chaîne se terminant par un point suivi d'au moins un caractère de [0-9a-z]
.
[
"foobar.a",
"foobar.txt",
"foobar.foobar1234"
].forEach( t =>
console.log(
t.match(/\.[0-9a-z]+$/i)[0]
)
)
si vous souhaitez également limiter l'extension à un certain nombre de caractères, vous devez remplacer le +
var patt1=/\.[0-9a-z]{1,5}$/i;
autoriserait au moins 1 et au plus 5 caractères après le point.
Essayer
var patt1 = /\.([0-9a-z]+)(?:[\?#]|$)/i;
Cette RegExp est utile pour extraire les extensions de fichier à partir d'URL, même celles qui ont des chaînes de requête ?foo=1
et des fins #hash
.
Il vous fournira également l'extension en tant que $1
.
var m1 = ("filename-jpg").match(patt1);
alert(m1); // null
var m2 = ("filename#gif").match(patt1);
alert(m2); // null
var m3 = ("filename.png").match(patt1);
alert(m3); // [".png", "png"]
var m4 = ("filename.txt?foo=1").match(patt1);
alert(m4); // [".txt?", "txt"]
var m5 = ("filename.html#hash").match(patt1);
alert(m5); // [".html#", "html"]
P.S. +1 pour @stema who offre de très bons conseils sur certaines des bases de la syntaxe RegExp impliquées.
Exemple de liste:
var fileExtensionPattern = /\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/gmi
//regex flags -- Global, Multiline, Insensitive
var ma1 = 'css/global.css?v=1.2'.match(fileExtensionPattern)[0];
console.log(ma1);
// returns .css
var ma2 = 'index.html?a=param'.match(fileExtensionPattern)[0];
console.log(ma2);
// returns .html
var ma3 = 'default.aspx?'.match(fileExtensionPattern)[0];
console.log(ma3);
// returns .aspx
var ma4 = 'pages.jsp#firstTab'.match(fileExtensionPattern)[0];
console.log(ma4);
// returns .jsp
var ma5 = 'jquery.min.js'.match(fileExtensionPattern)[0];
console.log(ma5);
// returns .js
var ma6 = 'file.123'.match(fileExtensionPattern)[0];
console.log(ma6);
// returns .123
BON MOT:
let ext = (filename.match(/\.([^.]*?)(?=\?|#|$)/) || [])[1]
la solution ci-dessus comprend des liens. Egzamples (nom de fichier -> ext):
// "abcd.Ef1" -> "Ef1"
// "abcd.efg" -> "efg"
// "abcd.efg?aaa&a?a=b#cb" -> "efg"
// "abcd.efg#aaa__aa?bb" -> "efg"
// "abcd" -> undefined
// "abcdefg?aaa&aa=bb" -> undefined
// "abcdefg#aaa__bb" -> undefined
Cela prend tout entre le dernier point et le premier caractère "?
" ou "#
" ou fin de chaîne. Pour ignorer les caractères "?
" et "#
", utilisez /\.([^.]*)$/
. Pour ignorer uniquement "#
", utilisez /\.([^.]*?)(?=\?|$)/
.