Подтвердить что ты не робот

Нужна функция basename в Javascript

Мне нужна короткая функция basename (однострочный?) для 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
4b9b3361

Ответ 1

function baseName(str)
{
   var base = new String(str).substring(str.lastIndexOf('/') + 1); 
    if(base.lastIndexOf(".") != -1)       
        base = base.substring(0, base.lastIndexOf("."));
   return base;
}

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

Ответ 2

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

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

Ответ 3

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

Более быстрая/более простая реализация должна использовать как можно меньше функций/операций. 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 разных вещи: удаление расширений, получение реального байта, получение вашего пользовательского базового имени. Я считаю это более элегантной версией, чем другие.

Ответ 4

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

Ответ 5

 basename = function(path) {
    return path.replace(/.*\/|\.[^.]*$/g, '');
 }

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

Ответ 6

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

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

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

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

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

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

Будет возвращено "need-a-basename-function-in-javascript".

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

Ответ 7

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

Ответ 8

Другое хорошее решение:

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
}

from: http://locutus.io/php/filesystem/basename/

Ответ 9

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

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

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

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

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

Ответ 10

Довольно просто использовать регулярное выражение:

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

Пояснение:

Соответствует одному символу точки, за которым следует любой символ, кроме точки ([^.]), один или несколько раз (+), привязанных к концу строки ($).

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

[EDIT] D'о. Не обращать внимания на вопрос - он тоже хочет сорвать путь. Ну, это все равно отвечает на половину вопроса.

Ответ 11

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


КОД:

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

Ответ 12

если исходная строка или текстовый файл содержит один символ обратной косой черты, вы можете найти его, используя '\'. в моих обстоятельствах я использую javascript для поиска индекса "\n" из текстового файла. и str.indexOf('\n'); помогли мне найти \N из исходной строки, которая считывается из исходного файла. надеюсь, что это поможет.

Ответ 13

ОБНОВИТЬ

Улучшенная версия, которая работает с прямой / и обратной косой чертой \ одинарной или двойной означает одно из следующих

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

Смотрите рабочее демо ниже

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>

Ответ 14

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

var basename = name => {return /([^\/]*)\.[^.]*$/gm.exec(name)[1];}