V3ntr1s
V3ntr1s

Reputation: 85

Need explanation of specific regex part -> "[^\}]"

I'm currently following some tutorial about PHP MVC framework to get better understanding of PHP implementation. At one point in tutorial regex is added to extract custom variables form URL for router component. Regex target is to extract variable name and variable value, but value is another regex.

Regex added:

"/\{([a-z-]+):([^\}]+)\}/"

Regex is used on this string:

(?P<controller>[a-z-]+)\/{id:\d+}\/(?P<action>[a-z-]+)

preg_match result: demo

array(
   0=>{id:\d+}
   1=>id
   2=>\d+
)

This code is working as intended, but my questions is WHY!?

Part I can't figure out is [^\\}]. By regex rules this should exclude characters inside [ ] but instead I get a full string as value from : to closed bracket }, I can also get same result on this string if I use [^}] or [^{}] or [^{] instead.

How does this [^\\}] part of regex work exactly???

Here is full implementation of "add" function

<?php

class Router {
  protected $routes = [];
  protected $params = [];

  //Add a route to the routing table
  public function add($route, $params = []){
    //convert the route to a regular expresion: escape forward slashes
    $route = preg_replace('/\//','\\/', $route);

    //Convert variables e.g. {controller}
    $route = preg_replace('/\{([a-z-]+)\}/','(?P<\1>[a-z-]+)', $route);

    //Convert variables with custom regular expressions e.g. {id:\d+}
    $route = preg_replace('/\{([a-z-]+):([^\}]+)\}/','(?P<\1>\2)', $route);

    //add start and end delimiters and case sensitive flag
    $route = '/^'.$route.'$/i';

    $this->routes[$route] = $params;
  }
}

And adding base string to routes

$router->add('{controller}/{id:\d+}/{action}');

Upvotes: 2

Views: 112

Answers (1)

Jingshao Chen
Jingshao Chen

Reputation: 3485

[^\}] has actually an extra \, [^\}] is the same as [^}].

What it means is a char that is not }. + means one or more the element before it. So ([^\}]+) or([^}]+) will match one or more char that is not a }, aggressively (means match as many as possible). Therefore, in your example, it matches \d+.

-- Edit according to comment where } does not need \ to escape.

Upvotes: 1

Related Questions