Reputation: 53
I want to check 'n' explode this string:
{$gallery#pager/collectionName/imageName/manual/no_effect/foo1/foo2/.../fooN}
to:
var_name[0] => 'gallery',
modul_name[0] => 'pager',
3[0] => 'collectionName',
4[0] => 'imageName',
5[0] => 'manual'
...
N[0] => 'fooN'
I made the following regexp:
/{\$(?P<var_name>[^#]+)#(?P<module_name>[^\/]+)(?:\/(\w+)(?:\/(\w+)(?:\/(\w+)(?:\/(\w+)(?:\/(\w+))?)?)?)?)?}/
, but it's too ugly and only support up to five parameters. Please help me to make a recursive part to extract all parameters.
ps: Yes, i can split this to var_name, module_name and paramters parts, then i can explode parameters part by '/', but i don't like it.
Upvotes: 5
Views: 437
Reputation: 6511
You could use preg_split()
.
Regex:
preg_split('@([$#])|[{}/]+@', $text)
And discard the first and third item in the array.
EDIT: To reflect new conditions specified by the OP in comments (not in the question): It should validate the syntax ^\{\$\w+#\w+(?:/\w*)$
and tokenize in var, module and parameters independently.
Regex:
~\G(?(?=^)\{\$(\w++)#(\w++)(?=[\w/]+}$))/\K\w*+~
\G
Matches at the beggining of string or at the end of last match.(?(?=^) ... )
If at start of string\{\$(\w++)#(\w++)(?=[\w/]+}$
Capture var and module, and validate syntax until the end of string./\K
Match 1 slash and reset matched text.\w*+
Match 1 parameter.Code:
// http://stackoverflow.com/q/32969465/5290909
$pattern = '@\G(?(?=^)\{\$(\w++)#(\w++)(?=[\w/]+}$))/\K\w*+@';
$text = '{$gallery#pager/collectionName/imageName/manual/no_effect/foo1/foo2/fooN}';
$result = preg_match_all($pattern, $text, $matches);
if ($result === 0) {
// is invalid, does not match '~^\{\$\w+#\w+(?:/\w*)+$~'
echo "Invalid text";
} else {
// Assign vars (only to clarify)
$module_name = array_pop($matches)[0];
$var_name = array_pop($matches)[0];
$parameters = $matches;
echo "VAR NAME: \t'$var_name'\nMODULE: \t'$module_name'\nPARAMETERS:\n";
print_r($matches);
}
Output:
VAR NAME: 'gallery'
MODULE: 'pager'
PARAMETERS:
Array
(
[0] => collectionName
[1] => imageName
[2] => manual
[3] => no_effect
[4] => foo1
[5] => foo2
[6] => fooN
)
Upvotes: 3
Reputation: 67968
{\$([^#]+)#|\G(?!^)([^\/]+)\/|\G(?!^)(.*?)}$
You can simply do a match instead and grab the groups
.See demo.
https://regex101.com/r/cJ6zQ3/18
$re = "/{\\$([^#]+)#|\\G(?!^)([^\\/]+)\\/|\\G(?!^)(.*?)}$/m";
$str = "{\$gallery#pager/collectionName/imageName/manual/no_effect/foo1/foo2/.../fooN}";
preg_match_all($re, $str, $matches);
Upvotes: 2