web-dev-qa-db-fra.com

JavaScript regex pour correspondre/extraire une extension de fichier

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.

27
mare

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].

Exemple:

[
  "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.

53
stema

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.

41
Már Örlygsson

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

Page de test .

9
AhbapAldirmaz

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 /\.([^.]*?)(?=\?|$)/.

0
Kamil Kiełczewski