douglas douglas - 4 months ago 7x
PHP Question

Match Expression Results to Variable

How do I match a pattern string with group of variables defined by

from a string that contains the
to an array?


I have the Pattern String:

$pattern = "Image_{{DATE}}.{{EXTENSION}}";

And I would like to pass the match string

$string = "Image_2016-05-26.png";

And after passing both strings to the function, return

$result = [
"DATE": "2016-05-26",
"EXTENSION": "png"

This includes, but not limited to the example variable:

$pattern = "Image_{{YEAR}}-{{MONTH}}-{{DAY}}.{{EXTENSION}}";
$string = "Image_2016-05-26.png";
// ------------------------------
$result = [
"YEAR" => "2016",
"MONTH" => "05",
"DAY" => "26",
"EXTENSION" => ".png"

(Optional, I think this is the hardest) But also only return values if they're found:

$pattern = "Image_{{DATE}}.{{EXTENSION}}";
$string = "Image_2016-05-26";
// ------------------------------
$result = [
"DATE" => "2016-05-26",

Is there any way to build a function passing
as variables and achieve



Here's the overview of the steps you would need to do:

First, escape all of the characters which have special meaning to regex, except for the {{ and the }}. Next, replace all instances of {{ with (?P<. Next, replace all instances of }} with >.*?). Then add the prefix of /^ and the suffix of $/ to the string.

That would convert the following pattern:


Into the following regex pattern:


Now, use that regex pattern to search for a match. Then loop through all the captured groups in the match and output the name/value pair for each one.

For instance, something like this will work for those examples:

function func_name($pattern, $string) {
    $pattern = "/^" . str_replace([".", "{{", "}}"], ["\.", "(?P<", ">.*?)"], $pattern) . "$/";
    preg_match($pattern, $string, $result);
    return array_filter($result, "is_string", ARRAY_FILTER_USE_KEY);

Of course, all of this would be much easier if your input pattern was a proper regex pattern to begin with...

As far as making the extension variable optional, you can make a capturing group optional by adding a ? after it, but there is no automated way of doing it according to your example because in your example, the . before the extension is also optional, but there is no indication in the input pattern that that is the case. In other words, you would need to convert it to /^Image_(?P<DATE>.*?)(?:\.(?P<EXTENSION>.*?))?$/, but there's no way of knowing, based only on that input pattern, that you would need to add the (?: ... )? optional group around the extension and the preceding period.