简体   繁体   中英

How to make my regex only return exact matches

I'm looking at building a super simple router in javaScript...so far I have this:

var match,routeMatcher,p;

var routes = {
    "/users/:uid/pictures/:uid" : "userpictures",
    "/users/:uid" : "user"
};

var url = "/users/1024/pictures/456";

for(var i in routes) {
    //need to cache this regex
    routeMatcher = new RegExp(i.replace(/:[^\s/]+/g, '([\\w-]+)'));
    if(url.match(routeMatcher)) {
        match = url.match(routeMatcher);
        p = routes[i];
        console.log(p);
    }
}

and here's a fiddle http://jsfiddle.net/D6txe/

This works. When I feed in a url like "users/1000" I get back the corresponding function name (just got to work out how to call the string as a function now). Problem is if I have two routes that are very similar as in my example the regex matches both. In the example above I'd ideally only like the second route to be matched but unfortunately both get matched, because of course the first is also a match.

Is there any way I can make the regex only return exact matches? I have another solution which would involve counting the forward slashes in the input url and only call routes with a matching number of forward slashes....but this seems rather inelegant.

Try this:

routeMatcher = new RegExp(i.replace(/:[^\s/]+/g, '([\\w-]+)') + "$");

If you also want to support a trailing / to also cover /users/1024/pictures/456/ , you can change your RegExp as follows:

routeMatcher = new RegExp(i.replace(/:[^\s/]+/g, '([\\w-]+)') + "/?$");

I am not totally sure whether this is what you need.

I use ^ and $ to make the regex matches the exact format of the path portion of the URL:

routeMatcher = new RegExp("^" + i.replace(/:[^\s\/]+/g, '([\\w-]+)') + "$");

If you are taking the path from window.location.pathname to do the matching, then it is probably OK.

Here's a variant that caches your regular expressions (note the '^' and '$' in the regex):

function Router(routes) {
    var route, routeExp, matchers = {};

    for (route in routes) {
        if (routes.hasOwnProperty(route)) {
            routeExp = '^' + route.replace(/:[^\s/]+/g, '([\\w-]+)') + '$';
            matchers[route] = new RegExp(routeExp);
        }
    }

    return function(url) {
        var match;
        for (route in matchers) {
            if (matchers.hasOwnProperty(route)) {
                if (match = url.match(matchers[route])) {
                    return {
                        route: route,
                        name: routes[route],
                        match: match.slice(1)
                    };
                }
            }
        }
    }
}

usage:

var router = new Router({
    "/users/:uid/pictures/:uid" : "userpictures",
    "/users/:uid" : "user"
});

var result = router("/users/1024/pictures/456");

console.log(result);
/*
{
    route: "/users/:uid/pictures/:uid",
    name: "userpictures"
    match: ["1024", "456"]
}
*/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM