PHP使用preg_replace匹配移除文件名可选前缀正则写法求助
PHP正则提取文件名目标值实现方案
需求说明
需要使用preg_replace函数匹配文件名开头可选的123456abcde_格式前缀并替换为空,最终提取前缀(若存在)后第一个下划线前的目标值,目标值格式为get-thisValue或getthisValue。
待处理文件名样例如下:
123456abcde_get-thisValue_more details - specific_20200728173715594600.zip 123456abcde_get-thisValue_more details_20200728173715594600.zip 123456abcde_getthisValue_more details - specific_20200728173715594600.zip 123456abcde_getthisValue_more details_20200728173715594600.zip 123456abcde_get-thisValue_20200728173715594600.zip 123456abcde_getthisValue_20200728173715594600.zip get-thisValue_more details - specific_20200728173715594600.zip get-thisValue_more details_20200728173715594600.zip getthisValue_more details - specific_20200728173715594600.zip getThisValue_more details_20200728173715594600.zip get-thisValue_20200728173715594600.zip getthisValue_20200728173715594600.zip
原有代码问题
原有实现的正则/^([\da-z])\1*_/m存在两个核心问题,无法适配所有场景:
- 正则逻辑错误:捕获组仅匹配单个数字或小写字母,
\1*表示重复匹配和第一个捕获字符完全相同的内容,无法匹配123456abcde这类数字+小写字母混合的前缀 - 未设置可选匹配:前缀部分没有加可选标记,遇到不带前缀的文件名时匹配失效
正确实现
方案1:修正preg_replace逻辑(匹配原有代码思路)
将替换正则修改为/^(?:[a-z0-9]+_)?/i,正则规则说明:
^锚定字符串开头位置(?:[a-z0-9]+_)非捕获组,匹配1位及以上数字/字母后跟下划线的前缀格式?将整个前缀组设置为可选匹配,存在前缀则匹配替换,不存在则直接跳过i修饰符兼容大小写字母,适配样例中getThisValue这类带大写字母的场景
实现代码:
$filename = '123456abcde_get-thisValue_more details - specific_20200728173715594600.zip'; // 移除开头可选的前缀 $trimmedName = preg_replace('/^(?:[a-z0-9]+_)?/i', '', $filename); // 截取第一个下划线前的内容即为目标值 $targetValue = substr($trimmedName, 0, strpos($trimmedName, '_')); echo $targetValue;
方案2:一步匹配提取(更简洁)
可以直接使用preg_match一次性捕获目标值,无需替换后再做字符串截取,正则为/^(?:[a-z0-9]+_)?([^_]+)/i,直接捕获可选前缀之后到第一个下划线之前的所有内容:
$filename = '123456abcde_get-thisValue_more details - specific_20200728173715594600.zip'; preg_match('/^(?:[a-z0-9]+_)?([^_]+)/i', $filename, $matches); $targetValue = $matches[1]; echo $targetValue;
验证结果
上述两种方案对所有给出的文件名样例均能正确提取目标值:
- 带
123456abcde_前缀的文件:自动移除前缀后提取到get-thisValue/getthisValue - 不带前缀的文件:直接提取开头到第一个下划线之间的
get-thisValue/getthisValue/getThisValue
内容的提问来源于stack exchange,提问作者Eazylle Concepcion
相关产品推荐
相关产品推荐

