Hur kan jag få filändelser med JavaScript?
Se koden:
var file1 = "50.xsl";
var file2 = "30.doc";
getFileExtension(file1); //returns xsl
getFileExtension(file2); //returns doc
function getFileExtension(filename) {
/*TODO*/
}
Svar #1
Nyare redigering: Många saker har förändrats sedan denna fråga först publicerades - det finns mycket riktigt bra information i wallacer's reviderade svar samt i VisioN's utmärkta genomgång
Redigera: Bara för att detta är det accepterade svaret; wallacers svar är faktiskt mycket bättre:
return filename.split('.').pop();
Mitt gamla svar:
return /[^.]+$/.exec(filename);
Borde fungera.
Redigera: Som svar på PhiLho:s kommentar, använd något som:
return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined;
Svar #2
return filename.split('.').pop();
Redigera:
Det här är en annan icke-regex-lösning som jag tycker är mer effektiv:
return filename.substring(filename.lastIndexOf('.')+1, filename.length) || filename;
Det finns vissa specialfall som hanteras bättre av VisioNs svar nedan, särskilt filer utan filändelse (.htaccess etc inkluderade).
Det är mycket presterande och hanterar hörnfall på ett möjligen bättre sätt genom att returnera "" istället för hela strängen när det inte finns någon punkt eller ingen sträng före punkten. Det är en mycket välgjord lösning, även om den är svår att läsa. Lägg in den i ditt hjälpbibliotek och använd den bara.
Gammal redigering:
En säkrare implementation om du kommer att stöta på filer utan filändelse, eller dolda filer utan filändelse (se Visios kommentar till Toms svar ovan) skulle vara något i den här stilen
var a = filename.split(".");
if( a.length === 1 || ( a[0] === "" && a.length === 2 ) ) {
return "";
}
return a.pop(); // feel free to tack .toLowerCase() here if you want
Om a.length är ett, är det en synlig fil utan filtillägg dvs. file
Om a[0] === "" och a.length === 2 är det en dold fil utan filändelse t.ex. .htaccess
Detta bör reda ut problem med de något mer komplexa fallen. När det gäller prestanda tror jag att denna lösning är något långsammare än regex i de flesta webbläsare. För de flesta vanliga ändamål bör dock denna kod vara fullt användbar.
Svar #3
Följande lösning är snabb och kort nog att använda i massoperationer och spara extra byte:
return fname.slice((fname.lastIndexOf(".") - 1 >>> 0) + 2);
Här är en annan enradig icke-regexp universell lösning:
return fname.slice((Math.max(0, fname.lastIndexOf(".")) || Infinity) + 1);
Båda fungerar korrekt med namn som inte har någon filändelse (t.ex. myfile) eller börjar med punkten . (t.ex. .htaccess):
"" --> ""
"name" --> ""
"name.txt" --> "txt"
".htpasswd" --> ""
"name.with.many.dots.myext" --> "myext"
Om du bryr dig om hastigheten kan du köra benchmark och kontrollera att de tillhandahållna lösningarna är de snabbaste, medan den korta är otroligt snabb:
Hur den korta fungerar:
- Metoden
String.lastIndexOfreturnerar den sista positionen av delsträngen (d.v.s.".") i den givna strängen (d.v.s.fname). Om delsträngen inte hittas returnerar metoden-1. - De "oacceptabla" positionerna för punkten i filnamnet är
-1och0, vilka respektive hänvisar till namn utan filändelse (t.ex."name") och till namn som börjar med punkt (t.ex.".htaccess"). - Nollfyll höger-skift-operator (
>>>) om den används med noll påverkar negativa tal och omvandlar-1till4294967295och-2till4294967294, vilket är användbart för att behålla filnamnet oförändrat i kantfallen (en slags trick här). String.prototype.sliceextraherar delen av filnamnet från den position som beräknades som beskrivs. Om positionsnumret är större än strängens längd returnerar metoden"".
Om du vill ha en tydligare lösning som fungerar på samma sätt (plus med extra stöd för fullständig sökväg), kolla följande utökade version. Denna lösning kommer att vara långsammare än tidigare enkla enraderslösningar men är mycket lättare att förstå.
function getExtension(path) {
var basename = path.split(/[\\/]/).pop(), // extract file name from full path ...
// (supports `\\` and `/` separators)
pos = basename.lastIndexOf("."); // get last position of `.`
if (basename === "" || pos < 1) // if file name is empty or ...
return ""; // `.` not found (-1) or comes first (0)
return basename.slice(pos + 1); // extract extension ignoring `.`
}
console.log( getExtension("/path/to/file.ext") );
// >> "ext"
Alla tre varianterna bör fungera i vilken webbläsare som helst på klientsidan och kan också användas i serversidan NodeJS-kod.
Svar #4
function getFileExtension(filename)
{
var ext = /^.+\.([^.]+)$/.exec(filename);
return ext == null ? "" : ext[1];
}
Testad med
"a.b" (=> "b")
"a" (=> "")
".hidden" (=> "")
"" (=> "")
null (=> "")
Också
"a.b.c.d" (=> "d")
".a.b" (=> "b")
"a..b" (=> "b")
Svar #5
Det finns en standardbiblioteksfunktion för detta i path-modulen:
import path from 'path';
console.log(path.extname('abc.txt'));
Utdata :
.txt
Så, om du bara vill ha formatet:
path.extname('abc.txt').slice(1) // 'txt'
Om det inte finns någon filändelse kommer funktionen att returnera en tom sträng:
path.extname('abc') // ''
Om du använder Node är path inbyggt. Om du riktar dig mot webbläsaren kommer Webpack att paketera en path-implementation åt dig. Om du riktar dig mot webbläsaren utan Webpack kan du inkludera path-browserify manuellt.
Det finns ingen anledning att göra stränguppdelning eller regex.
Svar #6
function getExt(filename)
{
var ext = filename.split('.').pop();
if(ext == filename) return "";
return ext;
}
Svar #7
var extension = fileName.substring(fileName.lastIndexOf('.')+1);
Svar #8
Om du hanterar webbadresser kan du använda:
function getExt(filepath){
return filepath.split("?")[0].split("#")[0].split('.').pop();
}
getExt("../js/logic.v2.min.js") // js
getExt("http://example.net/site/page.php?id=16548") // php
getExt("http://example.net/site/page.html#welcome.to.me") // html
getExt("c:\\logs\\yesterday.log"); // log
Demo: https://jsfiddle.net/squadjot/q5ard4fj/
