Есть ли встроенная функция javascript, похожая на os.path.join?

Есть ли встроенная функция javascript, которая работает аналогично python os.path.join? Я знаю, что могу присоединиться к строкам следующим образом:

['a', 'b'].join('/')

Проблема заключается в том, что если строки уже содержат ведущий/конечный "/", то они не будут соединены правильно, например:

['a/','b'].join('/')

Edit: Должен был указать, что я делаю эту клиентскую сторону.

Ответ 1

В настоящее время нет встроенного модуля, который будет выполнять соединение, не допуская дублирования разделителей. Если вы хотите лаконично, я просто напишу себе:

function pathJoin(parts, sep){
   var separator = sep || '/';
   var replace   = new RegExp(separator+'{1,}', 'g');
   return parts.join(separator).replace(replace, separator);
}

var path = pathJoin(['a/', 'b', 'c//'])

Ответ 2

Используйте модуль path. path.join - именно то, что вы ищете. Из документов:

path.join([path1][, path2][, ...])#Соедините все аргументы и нормализуйте полученный путь.

Аргументы должны быть строками. В v0.8 нестроковые аргументы молча игнорировались. В v0.10 и выше генерируется исключение.

Пример:

path.join('/foo', 'bar', 'baz/asdf', 'quux', '..')
// returns
'/foo/bar/baz/asdf'

path.join('foo', {}, 'bar')
// throws exception
TypeError: Arguments to path.join must be strings

Edit:

Я предположил, что вы используете Javascript на стороне сервера, например node.js. Если вы хотите использовать его в браузере, вы можете использовать path-browserify.

Ответ 3

Опираясь на ответ @Berty, этот вариант ES6 сохраняет все начальные косые черты для работы с относительным URL протокола (например, //stackoverflow.com), а также игнорирует все пустые части:

build_path = (...args) => {
  return args.map((part, i) => {
    if (i === 0) {
      return part.trim().replace(/[\/]*$/g, '')
    } else {
      return part.trim().replace(/(^[\/]*|[\/]*$)/g, '')
    }
  }).filter(x=>x.length).join('/')
}
  • build_path("http://google.com/", "my", "path") вернет "http://google.com/my/path"
  • build_path("//a", "", "/", "/b/") вернет "//a/b"
  • build_path() вернет ""

Ответ 4

Вы можете найти полезный код в этом gist "Простые пути для соединения и функции dirname для общего javascript" (т.е. как в node и браузер)

// Joins path segments.  Preserves initial "/" and resolves ".." and "."
// Does not support using ".." to go above/outside the root.
// This means that join("foo", "../../bar") will not resolve to "../bar"
function join(/* path segments */) {
  // Split the inputs into a list of path commands.
  var parts = [];
  for (var i = 0, l = arguments.length; i < l; i++) {
    parts = parts.concat(arguments[i].split("/"));
  }
  // Interpret the path commands to get the new resolved path.
  var newParts = [];
  for (i = 0, l = parts.length; i < l; i++) {
    var part = parts[i];
    // Remove leading and trailing slashes
    // Also remove "." segments
    if (!part || part === ".") continue;
    // Interpret ".." to pop the last segment
    if (part === "..") newParts.pop();
    // Push new path segments.
    else newParts.push(part);
  }
  // Preserve the initial slash if there was one.
  if (parts[0] === "") newParts.unshift("");
  // Turn back into a single string path.
  return newParts.join("/") || (newParts.length ? "/" : ".");
}

// A simple function to get the dirname of a path
// Trailing slashes are ignored. Leading slash is preserved.
function dirname(path) {
  return join(path, "..");
}

Примечание аналогичные реализации (которые также могут быть преобразованы в код js) существуют для php здесь

Ответ 5

Принятый ответ не работает для URL, он удаляет двойную косую черту после протокола
https://hostname становится https:/hostname.

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

Ниже приведена модифицированная версия принятого ответа:

function pathJoin(parts, sep){
    const separator = sep || '/';
    parts = parts.map((part, index)=>{
        if (index) {
            part = part.replace(new RegExp('^' + separator), '');
        }
        if (index !== parts.length - 1) {
            part = part.replace(new RegExp(separator + '$'), '');
        }
        return part;
    })
    return parts.join(separator);
 }

использование:

console.log(pathJoin(['https://', 'hostname', 'path/'])); // 'https://hostname/path/'
console.log(pathJoin(['relative/', 'path', 'to/dir/']));  // 'relative/path/to/dir/'
console.log(pathJoin(['/absolute/', 'path', 'to/file'])); // '/absolute/path/to/file'

https://jsfiddle.net/tdsLencu/

Ответ 6

Мой подход к решению этой проблемы:

var path = ['a/','b'].map(function (i) {
    return i.replace(/(^\/|\/$)/, '');
}).join('/');

Второй метод:

var path = ['a/','b'].join('/').replace(/\/{2,}/, '/')

Ответ 7

Нет, однако его довольно легко реализовать. Это также можно было бы решить с помощью регулярного выражения, но это было бы неплохо без него.

var pathJoin = function(pathArr){
    return pathArr.map(function(path){
        if(path[0] === "/"){
            path = path.slice(1);        
        }
        if(path[path.length - 1] === "/"){
            path = path.slice(0, path.length - 1);   
        }
        return path;     
    }).join("/");
}

http://jsfiddle.net/swoogie/gfy50cm1/

Ответ 8

Это гарантирует, что он работает с ссылками http://, не удаляя двойную косую черту. Он обрезает косые черты в начале и в конце каждой части. Затем присоединяется к ним, разделенным символом '/'

/**
 * Joins 2 paths together and makes sure there aren't any duplicate seperators
 * @param parts the parts of the url to join. eg: ['http://google.com/', '/my-custom/path/']
 * @param separator The separator for the path, defaults to '/'
 * @returns {string} The combined path
 */
function joinPaths(parts, separator) {
  return parts.map(function(part) { return part.trim().replace(/(^[\/]*|[\/]*$)/g, ''); }).join(separator || '/');
}