从路径中删除所有目录名的正则表达式(保留文件名)

11

我想从一个路径中删除所有目录名:

Payload/brownie.app/Info.plist

应该变成什么?

Info.plist

我应该使用什么正则表达式,还是可以在Java中使用String的replace()方法? 谢谢!

6个回答

22

尝试使用这个:

new File("Payload/brownie.app/Info.plist").getName()

此函数返回文件名,不包括目录路径。

示例:

String filename = new File("Payload/brownie.app/Info.plist").getName();
System.out.println(filename);

输出:

Info.plist

2
不是正则表达式,而是在我看来最好的(面向对象,易读)解决方案:+1 - user85421
我同意你的看法,@Carlos Heuberger ;) - Oscar Mederos
1
在使用File.getName()去除路径时要小心,如果你正在处理的路径可能来自另一个操作系统(比如Linux服务器解析上传文件的DOS路径),会出现问题。File.getName()只会去除操作系统认为是目录的部分。在Linux上,“C:\somedir\myfile.txt”是一个完全有效的文件名。 - codelahoma

11

不需要使用正则表达式,只需查找最后一个斜杠并使用子字符串:

int index = path.lastIndexOf(File.separatorChar);
String name = path.substring(index+1);

或者使用:

new File(path).getName();

这个解决方案的问题在于你可以有像这样的URL:.../somepage.html?rurl=/x/y/z/something.html - CrayonViolent
此外,确保检查极端情况,比如文件位于根目录或路径为null。 <code> if (path == null) return null; int index = path.lastIndexOf(File.separatorChar); String name = path.substring(index+1); return index == -1 ? null : path.substring( 0, index ); - Sileria
如果文件名以斜杠结尾,则无法正常工作。如果文件名没有路径(相对文件)并且只是文件名,则无法正常工作。根目录下的目录名称仅为“斜杠”时无法正常工作。无法处理反斜杠和来自其他系统的混合斜杠路径(Windows)。 - mjs

9
这涵盖了所有目录的范围,包括尾部或开头的斜杠。
到目前为止,其他人都没有......
public static String extractFilename(String path)  {  
    java.util.regex.Pattern p       = java.util.regex.Pattern.compile('^[/\\\\]?(?:.+[/\\\\]+?)?(.+?)[/\\\\]?$');
    java.util.regex.Matcher matcher = p.matcher(path);

    if ( matcher.find() ) {
        return matcher.group(1);
    }
    return null;
}

使用中:

println extractFilename("data\\\\path/to/file/RandomFile.pdf")
println extractFilename("RandomFile.pdf")
println extractFilename("RandomFile.pdf/")
println extractFilename("data\\\\path/to/file/RandomFile.pdf/")
println extractFilename("/data\\\\path/to/file/RandomFile.pdf/")
println extractFilename("/data\\\\path/to/file/RandomFile.pdf")
println extractFilename("/RandomFile.pdf")
println extractFilename("/RandomFile.pdf/")
println extractFilename("/")

打印

RandomFile.pdf
RandomFile.pdf
RandomFile.pdf
RandomFile.pdf
RandomFile.pdf
RandomFile.pdf
RandomFile.pdf
RandomFile.pdf
/

为Uday解释一下。实际上这是一个相当复杂的问题,我不确定今天是否能对所有内容进行论证,但我会尽力 :)

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

0: 整个正则表达式

^

1: 开始于

[/\\\\]?

2:斜杠或反斜杠(是的,一个需要四个斜杠,太疯狂了!)。可以出现一次或不出现,因此不是必需的。

(?:.+[/\\\\]+?)? 

第三步是比较复杂的。它旨在跳过除了与这个确切模式匹配的最后一个之外的其他所有内容,这是一个非捕获组 (?:... 我们正在寻找多次出现的任何字符,后面跟着一个斜线。

该组可以重复多次,但它是非贪婪的。因此,它是在说做这个,除非你匹配以下在 4 中解释的正则表达式。

但是,由于括号外面有问号,因此并不需要整个片段。例如,"/RandomFile.pdf/" 将不会在此处生成匹配项,并继续进行步骤 4。

然而,我现在发现这有点奇怪,因为 .+ 是贪婪的,但它仍然在寻找斜线进行匹配。可能是组的特性使其非贪婪,或者是 Java 模式语法中的一个错误。

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

4: 由于正则表达式适用于整个字符串,因此它也必须一直匹配到末尾。之前在第3次匹配中使用了非贪婪的+?,这意味着只有当其后面的正则表达式未匹配时,它才会匹配。我们的单词在$处,在括号内,该括号可能以斜杠结尾,也可能不是。如果没有文件名,只有斜杠,则我选择返回根路径作为文件名,因为它也是一个文件名(目录名)。

5: 括号是一个捕获组,这就是我们最终返回的内容。

希望这能更好地解释清楚。


这对我来说完美地解决了问题。我的路径中同时包含 / 和 \(从某个 ARM 编译器获取)。这个正则表达式完美地解决了问题。你能否写下正则表达式的解释?Java 正则表达式让我很困惑。 - Udayaditya Barua
1
我添加了一个解释,Uday ;) - mjs
这是唯一对我有效的解决方案。我在Windows上开发,但在Linux上运行服务,并且用户使用Internet Explorer从Windows上传文件。在这种情况下,我将拥有带有反斜杠的文件名。codelahoma的评论帮助我专注于这个解决方案。 - Miklos Krivan

3
使用正则表达式替换,String name = directory.replaceAll(".*/",""),就这么简单。

1
如果文件名以斜杠结尾,则无法工作。如果文件名没有路径(相对文件),则无法工作。仅适用于目录名称为根目录的“斜杠”。反斜杠和混合斜杠路径(Windows)也无法工作。 - mjs

1

如果你要处理一个由浏览器传递给Web服务器的文件路径,你无法确定它是DOS风格的路径、Unix风格的路径还是只是没有路径的文件名。如果你真的需要一个正则表达式,这应该可以解决:

String path = "Payload/brownie.app/Info.plist";
String filename = path.replaceFirst("(^.*[/\\\\])?([^/\\\\]*)$","$2");

这将适用于DOS、Unix或不存在的路径。

不过,如dogbane建议所示,使用子字符串会更易读,但如果您正在处理多平台输入,则需要添加逻辑来检查两种类型的文件分隔符。


1
最好还是使用Johan的更简单的正则表达式(我不知道为什么会忽视它),但要在其中添加反斜杠,类似于:".*[/\\\\]" - codelahoma

1

之前的答案都比使用完整的正则表达式简单。但是如果你真的想使用一个,这里是一个你可以使用的正则表达式模式:".*/(.+)"

    Pattern p = Pattern.compile(".*/(.+)");
    Matcher matcher = p.matcher("Payload/brownie.app/Info.plist");

    if ( matcher.find() ) {
        System.out.println("result: "+matcher.group(1));
    }

从其他答案中可以看出,这比严格需要的代码更多,但如果您正在进行更复杂的模式匹配和字符串提取,则正则表达式是一个不错的选择。


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