如何从 JavaScript 中的字符串修剪文件扩展名?

Posted

技术标签:

【中文标题】如何从 JavaScript 中的字符串修剪文件扩展名?【英文标题】:How to trim a file extension from a String in JavaScript? 【发布时间】:2011-05-14 02:47:44 【问题描述】:

例如,假设x = filename.jpg,我想得到filename,其中filename可以是任何文件名(我们假设文件名只包含[a-zA-Z0-9-_]以简化.).

我在DZone Snippets 上看到了x.substring(0, x.indexOf('.jpg')),但x.substring(0, x.length-4) 的表现不是更好吗?因为length 是一个属性,不做字符检查,而indexOf() 是一个函数,做字符检查。

【问题讨论】:

见:Regular expression to remove a file's extension,另见:How can i get file extensions with javascript? 和***.com/questions/1991608/…差不多。除非你做很多这样的事情,否则担心效率就是过早的优化。 在 ES6 时代,还可以查看 Path 模块——以防你使用的是 nodejs 或适当的转译 【参考方案1】:

我喜欢使用正则表达式来做到这一点。它简短易懂。

for (const regexPattern of [
  /\..+$/,  // Find the first dot and all the content after it.
  /\.[^/.]+$/ // Get the last dot and all the content after it.
  ]) 
  console.log("myFont.ttf".replace(regexPattern, ""))
  console.log("myFont.ttf.log".replace(regexPattern, ""))


/* output
myFont
myFont
myFont
myFont.ttf
*/

上面的解释可能不是很严谨。如果想得到更准确的解释可以去regex101查看

\..+$ \.[^/.]+$

【讨论】:

【参考方案2】:

node.js中,不带扩展名的文件名可以如下获取。

const path = require('path');
const filename = 'hello.html';
    
path.parse(filename).name;     //=> "hello"
path.parse(filename).ext;      //=> ".html"
path.parse(filename).base; //=> "hello.html"

Node.jsdocumentation 页面的进一步解释。

【讨论】:

这个答案仅限于服务器端节点。如果您尝试在反应代码中使用它,它似乎不会导入。 如果您想从包含目录的路径中删除扩展名,您可以执行var parsed = path.parse(filename) 后跟path.join(parsed.dir, parsed.name) 另一种可能是let base = path.basename( file_path, path.extname( file_path ) )【参考方案3】:

如果知道扩展名的长度,可以使用x.slice(0, -4)(其中4是扩展名和点的三个字符)。

如果您不知道长度,@John Hartsock regex 将是正确的方法。

如果你不想使用正则表达式,你可以试试这个(性能较差):

filename.split('.').slice(0, -1).join('.')

请注意,它会在没有扩展名的文件上失败。

【讨论】:

我最喜欢这个解决方案。它很干净,我可以使用它,因为我知道文件扩展名始终是.jpg。我一直在寻找像 Ruby 的 x[0..-5]x.slice(0, -4) 之类的东西,看起来很棒!谢谢!并感谢其他所有人提供的所有其他强大的替代方案! 这不是最佳解决方案,请查看以下其他解决方案。 如果你不能 100% 确定扩展的长度,那么不要这样:"picture.jpeg".slice(0, -4) -> "picture." 这是一个危险的解决方案,因为你并不真正知道格式的长度。 "如果你知道扩展的长度" 几十年前,这是一个可以接受的假设。不要再使用这个了。【参考方案4】:

Node.js 从完整路径保存目录中删除扩展

https://***.com/a/31615711/895245 例如path/hello.html -> hello,但如果你想要path/hello.html -> path/hello,你可以使用这个:

#!/usr/bin/env node
const path = require('path');
const filename = 'path/hello.html';
const filename_parsed = path.parse(filename);
console.log(path.join(filename_parsed.dir, filename_parsed.name));

还有输出目录:

path/hello

https://***.com/a/36099196/895245 也实现了这一点,但我发现这种方法在语义上更令人愉悦。

在 Node.js v10.15.2 中测试。

【讨论】:

【参考方案5】:

我不知道这是否是一个有效的选项,但我使用这个:

name = filename.split(".");
// trimming with pop()
name.pop();
// getting the name with join()
name.join('.'); // we split by '.' and we join by '.' to restore other eventual points.

这不仅仅是我知道的一种操作,但至少它应该始终有效!

更新:如果你想要一个单线,你在这里:

(name.split('.').slice(0, -1)).join('.')

【讨论】:

不应该是name.join(''),而是name.join('.')。你用点分隔,但用逗号连接,所以hello.name.txt 返回hello, name 文件名.split(".").shift();【参考方案6】:

虽然已经很晚了,但我将添加另一种方法来使用普通的旧 JS 获取不带扩展名的文件名-

path.replace(path.substr(path.lastIndexOf('.')), '')

【讨论】:

path.split('.').pop() 用于部分文件扩展名 他实际上是在尝试获取文件名,而不是扩展名!【参考方案7】:

我喜欢这个,因为它是一个不难阅读的单行:

filename.substring(0, filename.lastIndexOf('.')) || filename

【讨论】:

【参考方案8】:

这是我用来从文件名中删除扩展名的代码,不使用正则表达式或 indexOf(IE8 不支持 indexOf)。它假定扩展名是最后一个 '.' 之后的任何文本。字符。

适用于:

没有扩展名的文件:“myletter” 带有“.”的文件在名称中:“my.letter.txt” 未知长度的文件扩展名:“my.letter.html”

代码如下:

var filename = "my.letter.txt" // some filename

var substrings = filename.split('.'); // split the string at '.'
if (substrings.length == 1)

  return filename; // there was no file extension, file was something like 'myfile'

else

  var ext = substrings.pop(); // remove the last element
  var name = substrings.join(""); // rejoin the remaining elements without separator
  name = ([name, ext]).join("."); // readd the extension
  return name;

【讨论】:

hello.tar.gz 失败,输出为hellotar #AsifAli 谢谢你是对的,我忘了读取文件扩展名。我已经更新了答案,我希望它现在可以工作。【参考方案9】:
x.slice(0, -(x.split('.').pop().length + 1));

【讨论】:

虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。【参考方案10】:

x.length-4 仅考虑 3 个字符的扩展名。如果你有filename.jpegfilename.pl怎么办?

编辑:

回答...当然,如果您总是有.jpg 的扩展名,x.length-4 就可以了。

但是,如果您不知道扩展的长度,许多解决方案中的任何一个都更好/更健壮。

x = x.replace(/\..+$/, '');

x = x.substring(0, x.lastIndexOf('.'));

x = x.replace(/(.*)\.(.*?)$/, "$1");

OR(假设文件名只有一个点)

parts = x.match(/[^\.]+/);
x = parts[0];

OR(也只有一个点)

parts = x.split(".");
x = parts[0];

【讨论】:

?? 在这种情况下,您可以有一个文件名,例如:“summer.family.jpg” split('.')[0]将仅返回部分文件名。我会从答案中删除该问题,或者在该示例的问题下明确说明。 @basarat ... 关于零件分割我经常做的事情:var parts = full_file.split("."); var ext = parts[parts.length-1]; var file = parts.splice(0,parts.length-1).join("."); x.split(".") 甚至不应被视为答案。我知道我使用“。”在我几乎所有的文件命名约定中,即“survey.controller.js”或“my.family.jpg”。 @Lee2808:因此只有一个点的警告。这只是为了表明存在多种方法,具体取决于应用程序。在几乎所有情况下,我肯定会使用其他方法之一。 x = x.substr(0, x.lastIndexOf('.')); - 你的意思可能是x = x.substring(0, x.lastIndexOf('.'));【参考方案11】:

如果您必须处理包含完整路径的变量(例如:thePath = "http://***.com/directory/subdirectory/filename.jpg")并且您只想返回“文件名”,您可以使用:

theName = thePath.split("/").slice(-1).join().split(".").shift();

结果将是 theName == "filename";

要尝试它,请将以下命令写入 chrome 调试器的控制台窗口: window.location.pathname.split("/").slice(-1).join().split(".").shift()

如果您只需要处理文件名及其扩展名(例如:theNameWithExt = "filename.jpg"):

theName = theNameWithExt.split(".").shift();

结果会是theName == "filename",同上;

注意事项:

    第一个有点慢,因为执行得更多 操作;但在这两种情况下都有效,换句话说,它可以提取 来自给定字符串的不带扩展名的文件名,该字符串包含路径或带有 ex 的文件名。而第二种方法仅在给定变量包含带有 ext 的文件名(如 filename.ext)时才有效,但要快一些。 这两种解决方案都适用于本地文件和服务器文件;

但我不能说与其他答案的性能比较以及浏览器或操作系统的兼容性。

working sn-p 1:完整路径

var thePath = "http://***.com/directory/subdirectory/filename.jpg";
theName = thePath.split("/").slice(-1).join().split(".").shift();
alert(theName);
  

working sn-p 2:带扩展名的文件名

var theNameWithExt = "filename.jpg";
theName = theNameWithExt.split("/").slice(-1).join().split(".").shift();
alert(theName);
  

working sn-p 2: 双扩展名的文件名

var theNameWithExt = "filename.tar.gz";
theName = theNameWithExt.split("/").slice(-1).join().split(".").shift();
alert(theName);
  

【讨论】:

【参考方案12】:

简单一:

var n = str.lastIndexOf(".");
return n > -1 ? str.substr(0, n) : str;

【讨论】:

【参考方案13】:

您可以使用path 进行操作。

var MYPATH = '/User/HELLO/WORLD/FILENAME.js';
var MYEXT = '.js';
var fileName = path.basename(MYPATH, MYEXT);
var filePath = path.dirname(MYPATH) + '/' + fileName;

输出

> filePath
'/User/HELLO/WORLD/FILENAME'
> fileName
'FILENAME'
> MYPATH
'/User/HELLO/WORLD/FILENAME.js'

【讨论】:

【参考方案14】:

不确定什么会执行得更快,但是当涉及到.jpeg.html 等扩展时,这会更可靠

x.replace(/\.[^/.]+$/, "")

【讨论】:

您可能还想禁止 / 作为路径分隔符,因此正则表达式为 /\.[^/.]+$/ 这适用于任何长度的文件扩展名(.txt 或 .html 或 .htaccess),并且还允许文件名包含额外的句点 (.) 字符。它不会处理例如 .tar.gz 由于扩展本身包含一个句点。文件名包含附加句点比文件扩展名更常见。谢谢! @Vik “正确答案”和接受的答案之间存在差异。接受的答案就是对提出问题的人有帮助的答案。 我认为 Windows 平台可能存在问题,因为可能存在反斜杠。所以正则表达式应该是 /\.[^/\\.]+$/. @ElgsQianChen 这里是帮助您回答问题的好工具regexr.com【参考方案15】:
var fileName = "something.extension";
fileName.slice(0, -path.extname(fileName).length) // === "something"

【讨论】:

这是迄今为止唯一适用于完整路径的方法:path/name.ext -> paht/name 而不是仅仅返回name,但我宁愿使用fs.parse,尽管它是更详细一点:***.com/a/59576950/895245 我喜欢这个答案......添加到它:如果您事先知道扩展名(或者如果扩展名是一个变量,那么我觉得这样说:filename.slice(0, -'.zip'.length) 或 @987654328 @.【参考方案16】:

在 0.12.x 之前的 Node.js 版本中:

path.basename(filename, path.extname(filename))

当然这也适用于 0.12.x 及更高版本。

【讨论】:

path.parse answer 更简单。【参考方案17】:

接受的答案仅去除最后一个扩展部分 (.jpeg),这在大多数情况下可能是一个不错的选择。

我曾经不得不删除所有扩展名 (.tar.gz),并且文件名被限制为不包含点(所以 2015-01-01.backup.tar 不会有问题):

var name = "2015-01-01_backup.tar.gz";
name.replace(/(\.[^/.]+)+$/, "");

【讨论】:

【参考方案18】:

这是另一个基于正则表达式的解决方案:

filename.replace(/\.[^.$]+$/, '');

这应该只切断最后一段。

【讨论】:

【参考方案19】:

即使字符串中不存在分隔符,这也有效。

String.prototype.beforeLastIndex = function (delimiter) 
    return this.split(delimiter).slice(0,-1).join(delimiter) || this + ""


"image".beforeLastIndex(".") // "image"
"image.jpeg".beforeLastIndex(".") // "image"
"image.second.jpeg".beforeLastIndex(".") // "image.second"
"image.second.third.jpeg".beforeLastIndex(".") // "image.second.third"

也可以像这样用作单线:

var filename = "this.is.a.filename.txt";
console.log(filename.split(".").slice(0,-1).join(".") || filename + "");

编辑:这是一个更有效的解决方案:

String.prototype.beforeLastIndex = function (delimiter) 
    return this.substr(0,this.lastIndexOf(delimiter)) || this + ""

【讨论】:

【参考方案20】:

另一种衬里 - 我们假设我们的文件是 jpg 图片 >> 例如:var yourStr = 'test.jpg';

    yourStr = yourStr.slice(0, -4); // 'test'

【讨论】:

【参考方案21】:

您也许可以假设最后一个点将是扩展分隔符。

var x = 'filename.jpg';
var f = x.substr(0, x.lastIndexOf('.'));

如果文件没有扩展名,它将返回空字符串。要解决这个问题,请使用此功能

function removeExtension(filename)
    var lastDotPosition = filename.lastIndexOf(".");
    if (lastDotPosition === -1) return filename;
    else return filename.substr(0, lastDotPosition);

【讨论】:

警告,如果碰巧没有文件扩展名,则会失败。剩下一个空字符串。 不考虑点的较短版本。 var f = x.substr(0, x.lastIndexOf('.')) || x; 这是有效的,因为空字符串是虚假的,因此它返回 x。【参考方案22】:

另一条线:

x.split(".").slice(0, -1).join(".")

【讨论】:

【参考方案23】:

这就是正则表达式派上用场的地方! Javascript 的 .replace() 方法将采用正则表达式,您可以利用它来完成您想要的:

// assuming var x = filename.jpg or some extension
x = x.replace(/(.*)\.[^.]+$/, "$1");

【讨论】:

【参考方案24】:

我会使用类似 x.substring(0, x.lastIndexOf('.')) 的东西。如果您要追求性能,那就根本不要使用 javascript :-p 不,再多一条语句对于 99.99999% 的所有用途来说确实无关紧要。

【讨论】:

“如果你追求性能,就不要使用 javascript” - 你还建议在 Web 应用程序中使用什么......? 他没有提到网络应用程序。 这个问题是在 7 年前的 2010 年提出的,答案是在 2010 年发布的,当时 JavaScript 几乎只在 Web 应用程序中使用。 (Node 刚刚诞生,当时它甚至没有指南,也没有 NPM) ;-) 不过,如果性能对此类任务很重要,您可以考虑在后端执行此操作并在前端处理结果。

以上是关于如何从 JavaScript 中的字符串修剪文件扩展名?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 中的 BigQuery 用户定义函数不会修剪分区

如何从字符串中修剪/替换字符'\'或'"'?

修剪字符串中的多个字符

如何在javascript中验证之前修剪非必填字段

如何以标准方式修剪前导/尾随空格?

如何分解和修剪空白?