js 实现pathmatcher
PathMatcher 实现方法
基本概念
PathMatcher 用于匹配 URL 路径或文件路径,常用于路由系统或文件系统操作。JavaScript 中可通过正则表达式或字符串处理实现路径匹配功能。
正则表达式实现
通过正则表达式匹配路径模式,支持通配符和参数提取:
function pathMatcher(pattern, path) {
const regex = new RegExp('^' + pattern
.replace(/\*/g, '.*')
.replace(/\//g, '\\/')
.replace(/:(\w+)/g, '(?<$1>[^/]+)') + '$');
return path.match(regex);
}
// 示例用法
const result = pathMatcher('/users/:id/profile', '/users/123/profile');
console.log(result?.groups?.id); // 输出 "123"
通配符匹配
实现简单的通配符匹配功能,支持 * 匹配任意字符:
function wildcardMatch(pattern, path) {
const regex = new RegExp(`^${pattern.split('*').map(escapeRegExp).join('.*')}$`);
return regex.test(path);
}
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
// 示例
wildcardMatch('/api/*/detail', '/api/users/detail'); // true
路径参数解析
从路径中提取命名参数:
function extractParams(pattern, path) {
const paramNames = [];
const regexPattern = pattern.replace(/:(\w+)/g, (_, name) => {
paramNames.push(name);
return '([^/]+)';
});
const match = new RegExp(`^${regexPattern}$`).exec(path);
if (!match) return null;
return paramNames.reduce((params, name, index) => {
params[name] = match[index + 1];
return params;
}, {});
}
// 使用示例
const params = extractParams('/product/:category/:id', '/product/electronics/42');
// { category: 'electronics', id: '42' }
性能优化版本
对于高频使用的场景,可预先编译匹配模式:
class PathMatcher {
constructor(pattern) {
this.keys = [];
this.regex = this.compile(pattern);
}
compile(pattern) {
const tokens = pattern.split('/');
const parts = tokens.map(token => {
if (token.startsWith(':')) {
this.keys.push(token.slice(1));
return '([^/]+)';
}
return token;
});
return new RegExp(`^${parts.join('/')}$`);
}
match(path) {
const match = this.regex.exec(path);
if (!match) return null;
return this.keys.reduce((result, key, index) => {
result[key] = match[index + 1];
return result;
}, {});
}
}
// 使用示例
const matcher = new PathMatcher('/blog/:year/:month/:slug');
const result = matcher.match('/blog/2023/10/hello-world');
// { year: '2023', month: '10', slug: 'hello-world' }
路径前缀匹配
检查路径是否以特定前缀开头:
function hasPathPrefix(path, prefix) {
return path.startsWith(prefix) &&
(path.length === prefix.length || path[prefix.length] === '/');
}
// 示例
hasPathPrefix('/admin/dashboard', '/admin'); // true
hasPathPrefix('/admin-dashboard', '/admin'); // false
路径规范化
处理路径中的 . 和 .. 等相对路径符号:

function normalizePath(path) {
const segments = path.split('/').filter(Boolean);
const stack = [];
for (const segment of segments) {
if (segment === '.') continue;
if (segment === '..') stack.pop();
else stack.push(segment);
}
return '/' + stack.join('/');
}
// 示例
normalizePath('/a/b/.././c//d'); // "/a/c/d"






