【发布时间】:2011-01-29 18:45:59
【问题描述】:
我想从路径中删除所有目录名:
Payload/brownie.app/Info.plist
应该变成
Info.plist
我应该使用什么正则表达式,或者我可以在 java 中使用 String 中的 replace() 吗? 谢谢!
【问题讨论】:
我想从路径中删除所有目录名:
Payload/brownie.app/Info.plist
应该变成
Info.plist
我应该使用什么正则表达式,或者我可以在 java 中使用 String 中的 replace() 吗? 谢谢!
【问题讨论】:
试试这个:
new File("Payload/brownie.app/Info.plist").getName()
这将返回不带目录的文件名。
例子:
String filename = new File("Payload/brownie.app/Info.plist").getName();
System.out.println(filename);
输出:
Info.plist
【讨论】:
File.getName() 去除路径,如果您正在使用的路径可能来自另一个操作系统(例如解析上传文件的 DOS 路径的 Linux 网络服务器)。 File.getName() 只删除操作系统认为是目录的任何内容。 "C:\somedir\myfile.txt" 在 Linux 上是一个完全有效的文件名。
您不需要正则表达式。只需找到最后一个斜杠并使用子字符串:
int index = path.lastIndexOf(File.separatorChar);
String name = path.substring(index+1);
或使用:
new File(path).getName();
【讨论】:
if (path == null) return null; int index = path.lastIndexOf(File.separatorChar);字符串名称 = path.substring(index+1);返回索引 == -1 ? null : path.substring(0, index);
这涵盖了所有频谱目录、尾部或起始斜线。
到目前为止,这里的所有其他人都没有...
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
/
.................................................. ........................编辑......................... ..................................................... .
对乌代的解释。这实际上是一个相当复杂的问题,我不确定我今天是否能证明所有这些,但我会试一试:)
^[/\\\\]?(?:.+[/\\\\]+?)?(.+?)[/\\\\]?$
0:整个正则表达式
^
1:以
开头[/\\\\]?
2:正斜杠或反斜杠(是的,四个斜杠为一个,疯了!)。一次或一次都没有,所以不需要。
(?:.+[/\\\\]+?)?
3:这一步比较复杂。它旨在跳过除最后一个与此精确模式匹配的所有内容,一个非捕获组 (?:... 我们是否多次查找任何字符,后跟一个斜杠。
组可以重复多次,但不贪心。所以它是说这样做,除非你匹配4中解释的以下正则表达式。
不过,这整个部分不是必需的,因为 ?括号外。比如“/RandomFile.pdf/”这里就不会产生匹配,继续4。
但是,现在我确实觉得这有点奇怪,因为 .+ 是贪婪的,它仍然期待匹配的斜线。这可能是组的性质,它们是非贪婪的,或者是 Java 模式语法中的错误。
(.+?)[/\\\\]?$
4:由于正则表达式适用于所有字符串,因此它还必须匹配到末尾。 3 的前一个匹配是非贪婪的,不愿意使用 +?,这意味着它只会匹配,只要它之后的正则表达式也不匹配。我们的词在末尾 $ 在括号内,可能以斜杠结尾,也可能不以斜杠结尾。如果没有文件名,我选择将根路径作为文件名返回,而只是一个斜杠,因为它也是一个文件名(目录名)
5:括号是一个捕获组,这是我们最后返回的。
我希望这能澄清一点。
【讨论】:
用正则表达式替换,String name = directory.replaceAll(".*/",""),就这么简单。
【讨论】:
前面的答案都比使用成熟的正则表达式更简单。但是,如果您真的想使用一个,可以使用以下正则表达式模式:".*/(.+)"
Pattern p = Pattern.compile(".*/(.+)");
Matcher matcher = p.matcher("Payload/brownie.app/Info.plist");
if ( matcher.find() ) {
System.out.println("result: "+matcher.group(1));
}
正如您从其他答案中看到的那样,这比严格需要的代码要多,但如果您要进行更复杂的模式匹配和字符串提取,那么正则表达式是一个不错的选择。
【讨论】:
如果您正在处理由浏览器传递给 Web 服务器的文件路径,您无法确定它是 DOS 风格的路径、Unix 风格的路径,还是只是没有路径的文件名。如果你真的想要一个正则表达式,应该这样做:
String path = "Payload/brownie.app/Info.plist";
String filename = path.replaceFirst("(^.*[/\\\\])?([^/\\\\]*)$","$2");
无论有 DOS、Unix 还是缺少路径,这都可以工作。
不过,将子字符串用作 dogbane suggests 会更清晰易读,但会添加逻辑来检查两种类型的文件分隔符(同样,仅当您处理多平台输入时)。
【讨论】:
".*[/\\\\]"