如何使 preg_replace 处理忽略文件名,文件扩展名?

How to make preg_replace to process file name ignoring , file extension?

我有一个文件名为 Dona&ld #Duck .jpg。我想用 _ (下划线)替换 .jpg 或任何文件扩展名之前的所有特殊字符。 输出应该是 Don_a_ld__Duck__.jpg

如何使用 preg_replace 实现此目的?我做了如下。

$fileName ='Don.a&ld #Duck .jpg';
$fileName = trim($fileName);
$fileExtension = substr($fileName,-4);
$fileName = substr($fileName,0,-4); // file name without extension
echo $filename = preg_replace('/[^a-z0-9]/i', '_', $fileName).$fileExtension; 

我不想单独附加文件扩展名。

您可以使用前瞻性正则表达式:

$fileName = preg_replace('/\W(?=.*\.[^.]+$)/', '_', $fileName);
//=> Dona_ld__Duck__.jpg

\W(?=.*\.[^.]+$) 将匹配后跟点和任何扩展名的非单词字符。

RegEx Demo

使用以下具有保护最后一个点的负前瞻的解决方案:

$fileName ='Don.a&ld #Duck .jpg';
echo $filename = preg_replace('/[^a-z0-9](?![^.]*$)/i', '_', $fileName);
                                          ^^^^^^^^^ 

PHP demo

如果一个特殊字符后跟 0+ 个字符而不是一个点直到字符串末尾,(?![^.]*$) 只会失败匹配。

注意/[^a-z0-9]/i匹配_并替换为_,这是一个多余的操作。您可以使用 \W 子模式来避免它:

preg_replace('/\W(?![^.]*$)/', '_', $fileName)