web-dev-qa-db-fra.com

Besoin d'une fonction de base en Javascript

J'ai besoin d'une fonction de nom de base courte (one-liner?) Pour Javascript:

basename("/a/folder/file.a.ext") -> "file.a"
basename("/a/folder/file.ext") -> "file"
basename("/a/folder/file") -> "file"

Cela devrait dépouiller le chemin et toute extension.

Mise à jour: Pour les points au début, il serait agréable de traiter les fichiers "spéciaux"

basename("/a/folder/.file.a.ext") -> ".file.a"
basename("/a/folder/.file.ext") -> ".file"
basename("/a/folder/.file") -> ".file" # empty is Ok
basename("/a/folder/.fil") -> ".fil"  # empty is Ok
basename("/a/folder/.file..a..") -> # does'nt matter
43
PeterMmm
function baseName(str)
{
   var base = new String(str).substring(str.lastIndexOf('/') + 1); 
    if(base.lastIndexOf(".") != -1)       
        base = base.substring(0, base.lastIndexOf("."));
   return base;
}

Si vous pouvez utiliser à la fois / et \ comme séparateurs, vous devez modifier le code pour ajouter une ligne supplémentaire.

63
Nivas
function basename(path) {
   return path.split('/').reverse()[0];
}

Divise le chemin en répertoires de composants et nom_fichier renvoie ensuite le dernier élément (le nom_fichier) qui est le dernier élément du tableau.

58
Tomo Huynh

Tout ce qui précède fonctionne même s’ils n’ont aucun respect pour la vitesse/la mémoire :-).

Une implémentation plus rapide/plus simple devrait utiliser le moins de fonctions/opérations possible. RegExp est un mauvais choix car il consomme beaucoup de ressources alors qu'en réalité nous pouvons obtenir le même résultat mais plus facilement.

Une implémentation lorsque vous voulez que le nom de fichier comprenne l’extension (il s’agit en fait de la définition authentique du nom de base):

function basename(str, sep) {
    return str.substr(str.lastIndexOf(sep) + 1);
}

Si vous avez besoin d'une implémentation personnalisée de nom_base qui doit également effacer l'extension, je vous recommanderais plutôt une fonction spécifique d'élimination d'extension pour ce cas, que vous pourrez appeler à tout moment.

function strip_extension(str) {
    return str.substr(0,str.lastIndexOf('.'));
}

Exemple d'utilisation:

basename('file.txt','/'); // real basename
strip_extension(basename('file.txt','/')); // custom basename

Ils sont séparés de telle sorte que vous pouvez les combiner pour obtenir 3 choses différentes: supprimer l’extension, obtenir le nom de base réel, obtenir votre nom de base personnalisé. Je le considère comme une mise en œuvre plus élégante que d’autres approches.

18
Eugen Mihailescu

Peut-être essayer d'utiliser les paquets existants si vous le pouvez. http://nodejs.org/api/path.html

var path = require('path');
var str = '/path/to/file/test.html'

var fileNameStringWithoutExtention = path.basename(str, '.html');
// returns 'test'

// let path determine the extension
var fileNameStringWithoutExtention = path.basename(str, path.extname(str));
// returns 'test'

Autres exemples:

var pathString = path.dirname(str);
var fileNameStringWithExtention = path.basename(str);
var fullPathAndFileNameString = path.join(pathString, fileNameString);
9
Randy
 basename = function(path) {
    return path.replace(/.*\/|\.[^.]*$/g, '');
 }

remplace tout ce qui se termine par un slash .*\/ ou un point - certains non-dots - termine \.[^.]*$ par rien

6
user187291

Tout comme @ 3DFace a commenté:

path.split(/[\\/]/).pop(); // works with both separators

Ou si vous aimez les prototypes:

String.prototype.basename = function(sep) {
  sep = sep || '\\/';
  return this.split(new RegExp("["+sep+"]")).pop();
}

Essai:

var str = "http://stackoverflow.com/questions/3820381/need-a-basename-function-in-javascript";
alert(str.basename());

Renverra "besoin-un-nom-base-fonction-en-JavaScript".

Prendre plaisir!

2
Arthur Araújo

Une autre bonne solution:

function basename (path, suffix) {
  //  discuss at: http://locutus.io/php/basename/
  // original by: Kevin van Zonneveld (http://kvz.io)
  // improved by: Ash Searle (http://hexmen.com/blog/)
  // improved by: Lincoln Ramsay
  // improved by: djmix
  // improved by: Dmitry Gorelenkov
  //   example 1: basename('/www/site/home.htm', '.htm')
  //   returns 1: 'home'
  //   example 2: basename('ecra.php?p=1')
  //   returns 2: 'ecra.php?p=1'
  //   example 3: basename('/some/path/')
  //   returns 3: 'path'
  //   example 4: basename('/some/path_ext.ext/','.ext')
  //   returns 4: 'path_ext'

  var b = path
  var lastChar = b.charAt(b.length - 1)

  if (lastChar === '/' || lastChar === '\\') {
    b = b.slice(0, -1)
  }

  b = b.replace(/^.*[\/\\]/g, '')

  if (typeof suffix === 'string' && b.substr(b.length - suffix.length) === suffix) {
    b = b.substr(0, b.length - suffix.length)
  }

  return b
}

à partir de: http://locutus.io/php/filesystem/basename/

1
Arthur Araújo
function basename(url){
    return ((url=/(([^\/\\\.#\? ]+)(\.\w+)*)([?#].+)?$/.exec(url))!= null)? url[2]: '';
}
1
kennebec

Contrairement aux informations erronées fournies ci-dessus, les expressions régulières sont extrêmement efficaces. La mise en garde est que, lorsque cela est possible, ils devraient être en mesure de compiler exactement une fois dans la vie du programme.

Voici une solution qui donne à la fois dirname et basename .

const rx1 = /(.*)\/+([^/]*)$/;    // (dir/) (optional_file)
const rx2 = /()(.*)$/;            // ()     (file)

function dir_and_file(path) {
  // result is array with
  //   [0]  original string
  //   [1]  dirname
  //   [2]  filename
  return rx1.exec(path) || rx2.exec(path);
}
// Single purpose versions.
function dirname(path) {
  return (rx1.exec(path) || rx2.exec(path))[1];
}
function basename(path) {
  return (rx1.exec(path) || rx2.exec(path))[2];
}

En ce qui concerne les performances, je ne les ai pas mesurées, mais je m'attends à ce que cette solution soit dans la même plage que la plus rapide des autres sur cette page, mais cette solution en fait plus. Le fait que rx1 corresponde à la plupart des chemins actuels contribue à la performance réelle, si bien que rx2 est rarement exécuté. 

Voici un code de test.

function show_dir(parts) {
  console.log("Original str :"+parts[0]);
  console.log("Directory nm :"+parts[1]);
  console.log("File nm      :"+parts[2]);
  console.log();
}
show_dir(dir_and_file('/absolute_dir/file.txt'));
show_dir(dir_and_file('relative_dir////file.txt'));
show_dir(dir_and_file('dir_no_file/'));
show_dir(dir_and_file('just_one_Word'));
show_dir(dir_and_file('')); // empty string
show_dir(dir_and_file(null)); 

Et voici ce que le code de test donne:

# Original str :/absolute_dir/file.txt
# Directory nm :/absolute_dir
# File nm      :file.txt
# 
# Original str :relative_dir////file.txt
# Directory nm :relative_dir
# File nm      :file.txt
# 
# Original str :dir_no_file/
# Directory nm :dir_no_file
# File nm      :
# 
# Original str :just_one_Word
# Directory nm :
# File nm      :just_one_Word
# 
# Original str :
# Directory nm :
# File nm      :
# 
# Original str :null
# Directory nm :
# File nm      :null

A propos, "noeud" a un module intégré appelé "chemin" qui a "dirname" et "basename". La fonction "path.dirname ()" du noeud imite avec précision le comportement du "nom du répertoire" du shell "bash", mais est-ce bon? Voici ce qu'il fait: 

  1. Produit '.' (point) lorsque path=="" (chaîne vide). 
  2. Produit '.' (point) lorsque path=="just_one_Word"
  3. Produit '.' (point) lorsque path=="dir_no_file/".

Je préfère les résultats de la fonction définie ci-dessus.

1
IAM_AL_X

METTRE À JOUR

Une version améliorée qui fonctionne avec forward / et backslash \ simple ou double signifie l’un des éléments suivants

  • \\path\\to\\file
  • \path\to\file
  • //path//to//file
  • /path/to/file
  • http://url/path/file.ext
  • http://url/path/file

Voir une démo de travail ci-dessous

let urlHelper = {};
urlHelper.basename = (path) => {
  let isForwardSlash = path.match(/\/{1,2}/g) !== null;
  let isBackSlash = path.match(/\\{1,2}/g) !== null;

  if (isForwardSlash) {
    return path.split('/').reverse().filter(function(el) {
      return el !== '';
    })[0];
  } else if (isBackSlash) {
    return path.split('\\').reverse().filter(function(el) {
      return el !== '';
    })[0];
  }
  return path;
};

$('em').each(function() {
  var text = $(this).text();
  $(this).after(' --> <strong>' + urlHelper.basename(text) + '</strong><br>');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<em>http://folder/subfolder/file.ext</em><br>
<em>http://folder/subfolder/subfolder2</em><br>
<em>/folder/subfolder</em><br>
<em>/file.ext</em><br>
<em>file.ext</em><br>
<em>/folder/subfolder/</em><br>
<em>//folder//subfolder//</em><br>
<em>//folder//subfolder</em><br>
<em>\\folder\\subfolder\\</em><br>
<em>\\folder\\subfolder\\file.ext</em><br>
<em>\folder\subfolder\</em><br>
<em>\\folder\\subfolder</em><br>
<em>\\folder\\subfolder\\file.ext</em><br>
<em>\folder\subfolder</em><br>


Une solution plus simple pourrait être 

function basename(path) {
      return path.replace(/\/+$/, "").replace( /.*\//, "" );
}

Input                           basename()
/folder/subfolder/file.ext   --> file.ext
/folder/subfolder            --> subfolder
/file.ext                    --> file.ext
file.ext                     --> file.ext
/folder/subfolder/           --> subfolder

Exemple d'utilisation: https://jsfiddle.net/Smartik/2c20q0ak/1/

0
Muhammad Omer Aslam

si votre chaîne ou votre fichier texte d'origine contient une simple barre oblique inverse, vous pouvez le localiser à l'aide de '\'. Dans mon cas, javascript est utilisé pour trouver l'index de "\ N" à partir d'un fichier texte. et str.indexOf ('\ N'); m'a aidé à localiser le\N à partir de la chaîne d'origine qui est lue à partir du fichier source . espérons que cela aide.

0
Stevens
my_basename('http://www.example.com/dir/file.php?param1=blabla#cprod',   '/',  '?');
// returns:  file.php


CODE:

function my_basename(str, DirSeparator, FileSeparator) { var x= str.split(DirSeparator); return x[x.length-1].split(FileSeparator)[0];}
0
T.Todua

Assez simple avec regex:

function basename(input) {
   return input.split(/\.[^.]+$/)[0];
}

Explication:

Correspond à un seul point, suivi de tout caractère à l'exception d'un point ([^.]), une ou plusieurs fois (+), lié à la fin de la chaîne ($).

Il divise ensuite la chaîne en fonction de ce critère de correspondance et renvoie le premier résultat (c'est-à-dire tout ce qui précède la correspondance).

[EDIT] D'oh. Mal interprété la question - il veut aussi dégager le chemin. Oh bien, cela répond quand même à la moitié de la question.

0
Spudley