正则表达式:如何一次性获取不带扩展名的文件名?

24

我想使用正则表达式仅获取文件名,因此我尝试了一些简单的方法,例如

([^\.]*)

如果文件名有多个扩展名,普通的方法就不再起作用。但是,如果文件名是 adfadsfads.blah.txt,我只想要 adfadsfads.blah。如何通过正则表达式实现这一点?

关于David的问题,“为什么要使用正则表达式”,答案是“出于乐趣”。事实上,我正在使用的代码非常简单。

length_of_ext = File.extname(filename).length
filename = filename[0,(filename.length-length_of_ext)]

但是我喜欢尽可能地学习正则表达式,因为它总是在极客聚会上出现。


1
在这种情况下,我建议您购买像RegexBuddy这样的工具。如果您有这样的工具,使用正则表达式会更有趣。您甚至可以在这样的工具中调试正则表达式。我真的很推荐这个工具。 - David Pokluda
谢谢David。我使用Regex Coach,它的效果非常好。 - Dan Rosenstark
10个回答

55

试试这个:

(.+?)(\.[^.]*$|$)

这将会:

  • 捕获以点开头的文件名(例如.logs是一个名为.logs的文件,而不是文件扩展名),在Unix中很常见。
  • 获取除了最后一个点之外的所有内容:foo.bar.jpeg会得到foo.bar
  • 处理没有点的文件:secret-letter会得到secret-letter

注意:评论者j_random_hacker建议,为了可读性,您可能需要在之前加上锚点。


2
这个问题在http://www.movingtofreedom.org/2008/04/01/regex-match-filename-base-and-extension/有很好的解释。 - mechanical_meat
星号应该是加号,我认为 - 尽管不清楚一个名为“log.”的文件应该返回什么。 - Jonathan Leffler
1
虽然这个正则表达式按照宣传的那样工作,但是出于可读性的考虑,我能否建议在前面添加一个 "^" 锚点呢?如果没有这个锚点,第一次看到这个正则表达式的程序员需要执行详细分析来验证返回匹配是否始终从字符串开头开始。 - j_random_hacker
4
只保留一个捕获结果:(.+?)(?:.[^.]*$|$) - sebnow
当使用类似于 path/to/file/myfile.csv 的文件时。 - Alex Gordon
这似乎不能处理文件路径,只能处理文件名? - Mr. Boy

4

一个点后面跟着一个或多个不是点的字符,然后是字符串末尾:

(.+?)\.[^\.]+$

最后一个点号之前的所有内容被分组以便于检索。

如果您不能100%确定每个文件都有扩展名,请尝试:

(.+?)(\.[^\.]+$|$)

1
它不匹配没有扩展名的文件名。 - Dennis C

3
^(.*)\\(.*)(\..*)$
  1. 获取不含最后一个\的路径
  2. 不带扩展名的文件
  3. .的扩展名

示例:

c:\1\2\3\Books.accdb
(c:\1\2\3)(Books)(.accdb)

不支持文件名中有多个.,但支持文件路径中的.


3
如何使用两个捕获组,一个用于结尾,一个用于文件名。
例如:
(.+?)(?:\.[^\.]*$|$)

这一切都很好,但既然我会丢弃文件名,那还有什么必要呢?我想要一个只获取文件名的正则表达式。 - Dan Rosenstark
这个也不会匹配不带扩展名的文件名。 - j_random_hacker

1
我意识到这个问题有点过时,但是我在寻找一个好的来源时遇到了一些麻烦,最终自己制作了正则表达式。为了节省可能会发现这个问题的人的时间,
如果你正在寻找一个独立的正则表达式,
这将匹配扩展名而不带点。

\w+(?![\.\w])

这将始终匹配文件名,如果它有一个扩展名。 [\w\. ]+(?=[\.])

这些模式存在一些错误。具体来说,|+在字符类([])中不起作用。 - Kobi
糟糕,已修复。谢谢,这就是我使用正则表达式的原因。 - DarmaniLink

0

只返回文件名,不包括路径和后缀。

^.*[\\|\/](.+?)\.[^\.]+$

0

我使用了这个模式进行简单搜索:

^\s*[^\.\W]+$

对于这段文本:

file.ext
   fileext

   file.ext.ext
 file.ext
fileext

它在第二行和最后一行中找到fileext
我将其应用于文件夹的文本树视图中(使用空格缩进)。


0

这个正则表达式对我来说有效:

(.+(?=\..+$))|(.+[^\.])

结果 (加粗表示匹配成功):

  • test.txt
  • test 234!.something123
  • .test
  • .test.txt
  • test.test2.txt
  • .

0

好的,我不确定为什么要在这里使用正则表达式。如果我知道字符串是完整的文件路径,那么我会使用另一个API来获取文件名。正则表达式非常强大,但同时也相当复杂(你刚刚通过询问如何创建这样一个简单的正则表达式证明了这一点)。有人说过:你有一个问题,你决定使用正则表达式来解决它。现在你有两个问题了。

再想一想。例如,如果您在.NET平台上,则可以查看System.IO.Path类。


好吧,那不太有趣,是吗?无论如何,我已根据您的答案调整了问题,请参见上文。谢谢。 - Dan Rosenstark

0

尝试

(?<=[\\\w\d-:]*\\)([\w\d-:]*)(?=\.[\.\w\d-:]*)

从完整文件路径中仅获取任何类型的文件名。有意地排除了文件路径和文件扩展名。

例如:

C:\Log\test\bin\fee105d1-5008-410c-be39-883e5e40a33d.pdf
  • 无法捕获(C:\Log\test\bin)
  • 捕获(fee105d1-5008-410c-be39-883e5e40a33d)
  • 无法捕获(.pdf)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接