代码之家  ›  专栏  ›  技术社区  ›  PeterMmm

需要javascript中的basename函数

  •  44
  • PeterMmm  · 技术社区  · 14 年前

    我需要一个简短的basename函数(一行程序?)对于JavaScript:

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

    这将剥夺路径和任何扩展。

    更新: 对于一开始的dot,最好将其视为“特殊”文件。

    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
    
    13 回复  |  直到 6 年前
        1
  •  64
  •   Nivas    10 年前
    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
  •  60
  •   Tomo Huynh    11 年前
    function basename(path) {
       return path.split('/').reverse()[0];
    }
    

    将路径分解为组件目录和文件名,然后返回最后一个部分(文件名),它是数组的最后一个元素。

        3
  •  19
  •   Eugen Mihailescu    9 年前

    上面的任何一个都可以工作,尽管它们不尊重速度/内存:—)。

    更快/更简单的实现应该使用尽可能少的函数/操作。regexp是一个糟糕的选择,因为它消耗了大量的资源,而实际上我们可以获得相同的结果,但更容易。

    当需要包含扩展名的文件名(实际上是 真正的定义 基础名称):

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

    如果你需要定制 basename实现 它还必须去掉扩展,我建议您在这种情况下使用一个特定的扩展剥离函数,您可以随时调用它。

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

    使用实例:

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

    它们是分开的,这样您就可以将它们组合起来获得3种不同的东西:去掉扩展名、获取真实的基名、获取自定义的基名。我认为它比其他方法更优雅。

        4
  •  9
  •   Randy    10 年前

    如果可以的话,可以尝试使用现有的包。 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
  •  6
  •   user187291    14 年前
     basename = function(path) {
        return path.replace(/.*\/|\.[^.]*$/g, '');
     }
    

    替换以斜线结尾的任何内容 .*\/ 或点-一些非点-结束 \.[^.]*$ 一事无成

        6
  •  2
  •   Arthur Ronconi    8 年前

    就像@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
  •  1
  •   kennebec    14 年前
    function basename(url){
        return ((url=/(([^\/\\\.#\? ]+)(\.\w+)*)([?#].+)?$/.exec(url))!= null)? url[2]: '';
    }
    
        8
  •  1
  •   Arthur Ronconi    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
    }
    

    来自: http://locutus.io/php/filesystem/basename/

        9
  •  1
  •   IAM_AL_X    7 年前

    与上面提供的错误信息相反,正则表达式是非常有效的。警告是,如果可能的话,它们应该处于一个位置,以便在程序的生命周期中编译一次。

    这里有一个解决方案 目录名 基名 .

    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”有一个名为“path”的内置模块,它有“dirname”和“basename”。node的“path.dirname()”函数准确地模仿了“bash”shell的“dirname”的行为,但是这样做好吗?它的作用是:

    1. 生产 '.' (点)何时 path=="" (空字符串)。
    2. 生产 '' (点)何时 path=="just_one_word" .
    3. 生产 '' (点)何时 path=="dir_no_file/" .

    我更喜欢上面定义的函数的结果。

        10
  •  0
  •   Spudley Pat    14 年前

    使用regex相当简单:

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

    说明:

    匹配一个单点字符,后跟除点以外的任何字符( [^.] )一次或多次( + )绑定到字符串的结尾( $ )

    然后,它根据匹配条件拆分字符串,并返回第一个结果(即匹配前的所有内容)。

    [编辑] 哦。误读了这个问题——他也想把这条路也剥离掉。哦,好吧,不管怎样,这回答了一半的问题。

        11
  •  0
  •   T.Todua Laurent W.    9 年前
    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
  •  0
  •   Yuan    7 年前

    如果原始字符串或文本文件包含单个反斜杠字符,则可以使用'\'定位它。 在我的情况下,我使用javascript从文本文件中查找\n“的索引。str.indexof('\n');帮助我从源文件中读取的原始字符串中找到\n。 希望它有帮助。

        13
  •  0
  •   Muhammad Omer Aslam    6 年前

    更新

    一个改进的版本,与Forward一起工作 / 反斜线 \ 单或双表示以下任一项

    • \\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>

    一个更简单的解决方案可能是

    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
    

    工作示例: https://jsfiddle.net/Smartik/2c20q0ak/1/