Javascript 从单个正则表达式匹配文件名和文件扩展名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9001557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 08:21:22  来源:igfitidea点击:

Match filename and file extension from single Regex

javascriptjqueryregex

提问by Tom Bates

I'm sure this must be easy enough, but I'm struggling...

我相信这一定很容易,但我正在努力......

var regexFileName = /[^\]*$/; // match filename
var regexFileExtension = /(\w+)$/; // match file extension

function displayUpload() {
    var path = $el.val(); //This is a file input
    var filename = path.match(regexFileName); // returns  file name
    var extension = filename[0].match(regexFileExtension); // returns extension

    console.log("The filename is " + filename[0]);
    console.log("The extension is " + extension[0]);
}

The function above works fine, but I'm sure it must be possible to achieve with a single regex, by referencing different parts of the array returned with the .match() method. I've tried combining these regex but without success.

上面的函数工作正常,但我确信必须可以通过引用使用 .match() 方法返回的数组的不同部分,使用单个正则表达式来实现。我试过结合这些正则表达式但没有成功。

Also, I'm not using a string to test it on in the example, as console.log() escapes the backslashes in a filepath and it was starting to confuse me :)

另外,我没有在示例中使用字符串来测试它,因为 console.log() 转义了文件路径中的反斜杠,它开始让我感到困惑:)

采纳答案by Tim Pietzcker

Assuming that all files do have an extension, you could use

假设所有文件都有扩展名,您可以使用

var regexAll = /[^\]*\.(\w+)$/;

Then you can do

然后你可以做

var total = path.match(regexAll);
var filename = total[0];
var extension = total[1];

回答by shift66

/^.*\/(.*)\.?(.*)$/gafter this first group is your file name and second group is extention.

/^.*\/(.*)\.?(.*)$/g在第一组是您的文件名之后,第二组是扩展名。

var myString = "filePath/long/path/myfile.even.with.dotes.TXT";
var myRegexp = /^.*\/(.*)\.(.*)$/g;
var match = myRegexp.exec(myString);
alert(match[1]);  // myfile.even.with.dotes
alert(match[2]);  // TXT

This works even if your filename contains more then one dotes or doesn't contain dots at all (has no extention).
EDIT:
This is for linux, for windows use this /^.*\\(.*)\.?(.*)$/g(in linux directory separator is /in windows is \)

即使您的文件名包含多个点或根本不包含点(没有扩展名),这也有效。
编辑:
这是针对 linux,对于 windows 使用这个/^.*\\(.*)\.?(.*)$/g(在 linux 目录分隔符是/在 windows 中\

回答by fivedigit

You can use groups in your regular expression for this:

为此,您可以在正则表达式中使用组:

var regex = /^([^\]*)\.(\w+)$/;
var matches = filename.match(regex);

if (matches) {
    var filename = matches[1];
    var extension = matches[2];
}

回答by Alex Ander

This will recognize even /home/someUser/.aaa/.bb.c:

这甚至会识别/home/someUser/.aaa/.bb.c

function splitPathFileExtension(path){
    var parsed = path.match(/^(.*\/)(.*)\.(.*)$/);
    return [parsed[1], parsed[2], parsed[3]];
}

回答by Mark Smith

I know this is an old question, but here's another solution that can handle multiple dots in the name and also when there's no extension at all (or an extension of just '.'):
/^(.*?)(\.[^.]*)?$/

我知道这是一个老问题,但这里有另一种解决方案,它可以处理名称中的多个点,也可以在根本没有扩展名(或只有 '.' 的扩展名)时处理:
/^(.*?)(\.[^.]*)?$/

Taking it a piece at a time:
^
Anchor to the start of the string (to avoid partial matches)

一次取一块:
^
锚定到字符串的开头(以避免部分匹配)

(.*?)
Match any character ., 0 or more times *, lazily ?(don't just grab them all if the later optional extension can match), and put them in the first capture group ().

(.*?)
匹配任何字符.,0 次或多次*,懒惰地?(如果后面的可选扩展名可以匹配,不要只抓取它们),并将它们放在第一个捕获组中()

(\.
Start a 2nd capture group for the extension using (. This group starts with the literal .character (which we escape with \so that .isn't interpreted as "match any character").

(\.
使用 为扩展启动第二个捕获组(。该组以文字.字符开头(我们使用它进行转义,\因此不会.被解释为“匹配任何字符”)。

[^.]*
Define a character set []. Match characters notin the set by specifying this is an inverted character set ^. Match 0 or more non-.chars to get the rest of the file extension *. We specify it this way so that it doesn't match early on filenames like foo.bar.baz, incorrectly giving an extension with more than one dot in it of .bar.bazinstead of just .baz. .doesn't need escaped inside [], since everything (except^) is a literal in a character set.

[^.]*
定义一个字符集[]。通过指定这是一个反转字符集来匹配不在集合中的字符^。匹配 0 个或多个非.字符以获取文件扩展名的其余部分*。我们以这种方式指定它,这样它就不会在早期匹配文件名,例如foo.bar.baz,错误地给出一个包含多个点的扩展名.bar.baz而不是.baz. .不需要在里面转义[],因为所有内容(除了^)都是字符集中的文字。

)?
End the 2nd capture group )and indicate that the whole group is optional ?, since it may not have an extension.

)?
结束第二个捕获组)并指出整个组是可选的?,因为它可能没有扩展名。

$
Anchor to the end of the string (again, to avoid partial matches)

$
锚定到字符串的末尾(再次,避免部分匹配)

If you're using ES6 you can even use destructing to grab the results in 1 line:
[,filename, extension] = /^(.*?)(\.[^.]*)?$/.exec('foo.bar.baz'); which gives the filename as 'foo.bar'and the extension as '.baz'.
'foo'gives 'foo' and ''
'foo.'gives 'foo'and '.'
'.js'gives ''and '.js'

如果您使用的是 ES6,您甚至可以使用析构来获取 1 行中的结果:
[,filename, extension] = /^(.*?)(\.[^.]*)?$/.exec('foo.bar.baz'); 它给出了文件名 as'foo.bar'和扩展名 as '.baz'
'foo'给予'foo' and ''
'foo.'给予'foo''.'
'.js'给予'''.js'

回答by gabo bernal

I think this is a better approach as matches only valid directory, file names and extension. and also groups the path, filename and file extension. And also works with empty paths only filename.

我认为这是一个更好的方法,因为只匹配有效的目录、文件名和扩展名。并对路径、文件名和文件扩展名进行分组。并且也仅适用于空路径文件名。

^([\w\/]*?)([\w\.]*)\.(\w)$

Test cases

测试用例

the/p0090Aath/fav.min.icon.png
the/p0090Aath/fav.min.icon.html
the/p009_0Aath/fav.m45in.icon.css
fav.m45in.icon.css
favicon.ico

Output

输出

[the/p0090Aath/][fav.min.icon][png]
[the/p0090Aath/][fav.min.icon][html]
[the/p009_0Aath/][fav.m45in.icon][css]
[][fav.m45in.icon][css]
[][favicon][ico]