从路径中提取文件名

12

我需要从文件路径字符串中获取文件名。例如,从这个字符串\abc\def\filename.txt,我需要获取filename.txt

尝试使用正则表达式实现:

$filepath="abc\filename.txt";
$filename = preg_replace("/.+\\/","",$filepath);

但它会报错。我应该使用什么正则表达式来解决这个问题?


使用preg_replace将字符替换为null毫无意义,直接使用preg_match更加直接(请参阅我的答案)。 - Peter Ajtai
5个回答

40

你应该使用函数basename:

$filepath = 'abc\filename.txt';
$filename = basename($filepath);

编辑说明:重要提示,如果字符串中有反斜杠,请使用单引号,否则请适当转义。

注意:以下写法不会起作用:

$filepath = "abc\filename.txt";
$filename = basename($filepath);
因为您的变量 $filepath 实际上保存了如下内容: abc[special char here equalling \f]ilename.txt 另一个编辑: 这个正则表达式也可以运行。
$filepath = '\def\abc\filename.txt';
$basename = preg_replace('/^.+\\\\/', '', $filepath);

你原来的问题只在于你使用了双引号而不是单引号,并且反斜杠需要双重转义(\\ 而不是 \)。


@nathan:那样行不通,它会给你abcilename.txt - Sarfraz
@casablanca:希望其他人也尝试一下那段代码 :) 不过对我来说似乎不起作用。 - Sarfraz
@nathan:我认为问题出在\\上,basename在路径中使用/是正常的。 - Sarfraz
@sAc,你的问题已经得到了很好的解决,同时basename的修复也已经在编辑中完成——曾经让我们有些困惑! - nathan
@Billy:我也是这么想的,但出乎意料的是,PHP似乎无法解释\f - casablanca
显示剩余2条评论

5

两种解决方案:

  1. preg_match()
  2. str_replace()pathinfo()一起使用

1: preg_match()

好的,问题在于你正在使用反斜杠。你必须确保不要使用双引号来定义文件路径,因为反斜杠会被解释为转义序列。使用单引号。

此外,使用正则表达式更容易通过从路径末尾移动直到遇到反斜杠来获取文件名...诀窍是反斜杠是\\\\.. 这里有原因

最后,不要使用preg_replace。只需使用preg_match查找文件名:

<?php
  // Use single quotes or the backslash will be interpreted as an esacpe sequence
$filepath = '\abc\def\filename.txt';

  // You have to use 4 backslashes to represent your single backslash 
  // The regex picks the characters that are NOT \ from the end of the path
$pattern = '/[^\\\\]+$/';

  // Use $matches to store the match
preg_match($pattern, $filepath, $matches);

  // Display answer now, or use later
echo $matches[0];
?>

2: str_replace()pathinfo()

正如其他人所说,basename() 是一个很好的选择。如果后续可能需要目录或其他路径信息,则可以使用 pathinfo()

问题在于 basename 和 pathinfo 都假定使用斜杠“/”,因此您必须将反斜杠转换为斜杠“/”:

示例:

<?php
  // Make sure to use single quotes
$filepath='abc\filename.txt';
  // Replace backslash with forward slash
$filepath = str_replace('\\', '/', $filepath);
$path_parts = pathinfo($filepath);

  // This is the answer you want
echo $path_parts['basename'], "\n";

  // But you also have access to these
echo $path_parts['dirname'], "\n";
echo $path_parts['extension'], "\n";
echo $path_parts['filename'], "\n"; // since PHP 5.2.0
?>

那也行不通,而且他需要正则表达式的解决方案,正如他所指出的。 - Sarfraz
@sAc, 我认为OP表示正则表达式效果不是很好...我要走了,但过一会儿再试试。 - Peter Ajtai
只有在路径中使用斜杠(/)而不是反斜杠时才能正常工作。现在加1 :) - Sarfraz
@sAc 感谢提醒。我使用了一个非常简单的正则表达式重写了代码,它只获取路径末尾不是反斜杠的所有字符。同时,我还修复了原始代码中的斜杠替换问题。 - Peter Ajtai

3
这应该可以解决问题:
$filepath='abc\filename.txt';
$basename = preg_replace('/^.+[\\\\\\/]/', '', $filepath);
echo $basename;

结果:

filename.txt

这对于文件路径\abc\def\filename.txt是行不通的,它会返回"def\filename.txt"。 - nathan
@nathan:我相信问题出在 \\ 上,如果路径中使用 / 就可以正常工作。 - Sarfraz

1
preg_replace("/[^\/]+.([^\.]+\.[a-z]{3,5})/i","$1","abc/filename.txt"); //return filename.txt

0
为什么要在这样一个简单的问题上使用正则表达式?

$source = "/i/am/a/path.txt";
$pos = strrpos($source, '/');
$result = substr($source, $pos === FALSE ? 0 : $pos);

编辑:我还没有尝试过这个方法——我手头没有一个可用的PHP服务器。substr和strrpos可能存在一种偏移量错误,但如果是这种情况,您只需从$pos中加上或减去1即可。

编辑2:这里是反斜杠版本:

$source = "\\i\\am\\a\\path.txt";
$pos = strrpos($source, '\\');
$result = substr($source, $pos === FALSE ? 0 : $pos);

1
OP有反斜杠,所以您不能在$source中使用双引号,并且必须转义$pos中的反斜杠。 - Peter Ajtai
@Peter:添加了反斜杠版本。 - Billy ONeal

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