Нужна функция базового имени в Javascript - PullRequest
44 голосов
/ 29 сентября 2010

Мне нужна функция короткого базового имени (однострочная?) Для Javascript:

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

Это должно лишить путь и любое расширение.

Обновление: К точке в начале было бы неплохо относиться как к «особым» файлам

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

Ответы [ 14 ]

65 голосов
/ 29 сентября 2010
function baseName(str)
{
   var base = new String(str).substring(str.lastIndexOf('/') + 1); 
    if(base.lastIndexOf(".") != -1)       
        base = base.substring(0, base.lastIndexOf("."));
   return base;
}

Если вы можете использовать как /, так и \ в качестве разделителей, вы должны изменить код, чтобы добавить еще одну строку

61 голосов
/ 07 марта 2013
function basename(path) {
   return path.split('/').reverse()[0];
}

Разбивает путь на каталоги компонентов и имя файла, затем возвращает последний фрагмент (имя файла), который является последним элементом массива.

20 голосов
/ 29 апреля 2015

Любой из вышеперечисленных работает, хотя они не имеют никакого отношения к скорости / памяти: -).

Более быстрая / более простая реализация должна использовать как можно меньше функций / операций.RegExp - плохой выбор, потому что он потребляет много ресурсов, когда на самом деле мы можем достичь того же результата, но проще.

Реализация, когда вам нужно имя файла, включая расширение (которое фактически является подлинным определением базового имени):

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

Если вам нужна пользовательская реализация базового имени , которая должна также удалить расширение, я бы рекомендовал вместо этого использовать специальную функцию удаления расширения для этого случая,Вы можете вызывать его в любое время.

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

Пример использования:

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

Они разделены так, что вы можете объединить их, чтобы получить 3 разные вещи:удаление расширения, получение реального базового имени, получение пользовательского базового имени.Я считаю, что это более элегантная реализация, чем другие подходы.

11 голосов
/ 12 июля 2014

Возможно, попробуйте использовать существующие пакеты, если можете. 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'

Другие примеры:

var pathString = path.dirname(str);
var fileNameStringWithExtention = path.basename(str);
var fullPathAndFileNameString = path.join(pathString, fileNameString);
6 голосов
/ 29 сентября 2010
 basename = function(path) {
    return path.replace(/.*\/|\.[^.]*$/g, '');
 }

замените все, что заканчивается косой чертой .*\/ или точкой - некоторые не точки - конец \.[^.]*$ ничем

2 голосов
/ 02 августа 2016

Также как @ 3DFace прокомментировал:

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

Или, если вам нравятся прототипы:

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

Тестирование:

var str = "/2655305/nuzhna-funktsiya-bazovogo-imeni-v-javascript";
alert(str.basename());

Вернет "Need-a-basename-function-in-javascript".

Наслаждайтесь!

1 голос
/ 10 ноября 2017

Вопреки дезинформации, приведенной выше, регулярные выражения чрезвычайно эффективны. Предостережение заключается в том, что, когда это возможно, они должны находиться в таком положении, чтобы они компилировались ровно один раз за время существования программы.

Вот решение, которое дает dirname и 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];
}

Что касается производительности, я не измерял ее, но я ожидаю, что это решение будет в том же диапазоне, что и самое быстрое из других на этой странице, но это решение делает больше. В реальной производительности помогает тот факт, что rx1 будет соответствовать большинству реальных путей, поэтому rx2 выполняется редко.

Вот тестовый код.

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)); 

А вот что дает тестовый код:

# 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

Кстати, «узел» имеет встроенный модуль с именем «путь», который имеет «dirname» и «basename». Функция Node «path.dirname ()» точно имитирует поведение «dirname» оболочки «bash», но хорошо ли это? Вот что он делает:

  1. Создает '.' (точка), когда path=="" (пустая строка).
  2. Производит '.' (точка) при path=="just_one_word".
  3. Производит '.' (точка), когда path=="dir_no_file/".

Я предпочитаю результаты функции, определенной выше.

1 голос
/ 07 августа 2016

Еще одно хорошее решение:

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
}

от: http://locutus.io/php/filesystem/basename/

1 голос
/ 29 сентября 2010
function basename(url){
    return ((url=/(([^\/\\\.#\? ]+)(\.\w+)*)([?#].+)?$/.exec(url))!= null)? url[2]: '';
}
0 голосов
/ 07 мая 2019

Хорошая строка, использующая функции стрелки ES6:

var basename = name => {return /([^\/]*)\.[^.]*$/gm.exec(name)[1];}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...