I want to create my personal realpath() function which uses regex and doesn't expect that file exists.
What I did so far
function my_realpath (string $path): string {
if ($path[0] != '/') {
$path = __DIR__.'/../../'.$path;
}
$path = preg_replace("~/\./~", '', $path);
$path = preg_replace("~\w+/\.\./~", '', $path); // removes ../ from path
return $path;
}
What is not correct
The problem is if I have this string:
"folders/folder1/folder5/../../folder2"
it removes only first occurence (folder5/../):
"folders/folder1/../folder2"
Question
How to I remove (with regex) all folders followed by same number of "../" after them?
Examples
"folders/folder1/folder5/../../folder2" -> "folders/folder2"
"folders/folder1/../../../folder2" -> "../folder2"
"folders/folder1/folder5/../folder2" -> "folders/folder1/folder2"
Can we tell regex that: "~(\w+){n}/(../){n}~", n being greedy but same in both groups?
You can use a recursion-based pattern like
See the regex demo. Details:
(?<=/|^)- immediately to the left, there must be/or start of string (if the strings are served as separate strings, eqqual to a more efficient(?<![^/]))(?!\.\.(?![^/]))- immediately to the right, there should be no..that are followed with/or end of string[^/]+- one or more chars other than//- a/char(?R)?- recurse the whole pattern, optionally\.\.(?:/|$)-..followed with a/char or end of string.See the PHP demo:
Alternatively, you can use
See the regex demo. Details:
(?<![^/])- immediately to the left, there must be start of string or a/char(?!\.\.(?![^/]))- immediately to the right, there should be no..that are followed with/or end of string[^/]+- one or more chars other than//\.\.-/..substring followed with...(?:/|$)-/or end of string.See the PHP demo:
The
$countargument inpreg_replace('~(?<![^/])(?!\.\.(?![^/]))[^/]+/\.\.(?:/|$)~', '', $url, -1, $count)keeps the number of replacements, and the replacing goes on until no match is found.Output: