Two regex matches? One for each
Group regex patterns by values
I've the following example :
$str = "Jhon Doe 1990";
preg_match_all("/Jh(.*) D(.*) ([0-9]{4})/", $str, $matches);
echo $matches[1]; // on
echo $matches[2]; // oe
echo $matches[3]; // 1990
I want to group results by regex pattern
so it would be like :
[
'(.*)' => ['on','oe'] ,
'([0-9]{4})' => '[1990']
]
how can I achieve this?
thanks!
@Atef95 So, if I understand you correctly:
- you have a collection of monitors, which have a parent/child-type relationship to each other (e.g.,
Jhon Doe 1990may be the name of a parent monitor, which may have child/dependency monitors named something likeMonitor Network onand1991 Networks, for example) - your monitor names are ‘grouped’ so that a user can predict (their own?) monitor names
- the user can input regex patterns that should match specific (their own?) parent monitors
- you start out by using such a regex pattern to find parent monitors
- for each matched parent monitor, you then want to match child monitors by performing a regex match on child monitor names, using the child templates (regex patterns) provided by the user, but substituting the actual grouped matches from the parent template
If that is indeed what you’re trying to do, it isn’t possible using just simple regex. Your users will have to do some of the work for you. The best option, I think, would be to use named subpatterns, ensuring that your users adhere to a tight naming scheme that you can then process programmatically in PHP.
Simple option
If you don’t absolutely need to support multiple, grouped matches (e.g., for on or oe to be replaced into the same slot in Monitor Network (on|oe)), it would be fairly straightforward:
- You would instruct your users to use named subpatterns in the parent template and add references to those named subpatterns (in a syntax you define beforehand) in the child templates
Use
(?<name>pattern)to define a subpattern in the parent template.Use
{{name}}to refer to named subpatterns in the child templates.———
Example:
Parent –
Jh(?<a>.*) D(?<b>.*) (?<year>\d{4})Child –
Monitor Network ({{a}}|{{b}})or({{year}}) Networks
- In your backend code, you would then filter the array containing the matches from the parent template search to only retain the named matches, and then use another regex replacement to replace the references in the child templates with the relevant matches:
$parentMonitors = 'Jhon Doe 1990';
$parentTemplate = 'Jh(?<a>.*) D(?<b>.*) (?<year>\d{4})';
preg_match_all("/{$parentTemplate}/", $parentMonitors, $parentMatches);
$parentMatches = array_filter($parentMatches, "is_string", ARRAY_FILTER_USE_KEY);
// $parentMatches is now ['a' => 'on', 'b' => 'oe', 'year' => '1990']
$childTemplates = [
'Monitor Network ({{a}}|{{b}})',
'({{year}}) Networks'
];
foreach ($childTemplates as $t) {
preg_replace('/({{(.*)}})', fn($m) => $matches[$m[1]], $t);
}
// $childTemplates is now ['Monitor Network (on|oe)', '(1990) Networks']
(This is untested, so there are probably some errors in it here and there, but you get the gist of it.)
More complex options
If you do absolutely need to support grouping multiple patterns into one, you will need to instruct your users to make array-like subpattern names according to a syntax that you can then process to make actual arrays. Most of it would work as before, but there would be some added complexity. (I won’t go through that now in case you can do without it.)
Please or to participate in this conversation.