i have a list of key=>value pairs from a JSON squirt. i sorted the array and i’m left with the following (excerpted relevant cases because they go as high as 92):
dir1summary dir10summary dir1summarydue dir10summarydue directive1 directive10 directivecode1 directivecode10
what i need to do is: 1) place all the digits at the end and 2) pad them to 2 digits (01,02,&c) so the list ends up looking like this:
directivesummary01 directivesummary10 directivesummarydue01 directivesummarydue10 directive01 directive10 directivecode01 directivecode10
i was hoping to do this with one REGEX statement given the obvious similarity in key names, but i got lost. here’s what i have so far:
dir((d{1,2}(summary|summarydue))|((ectived{1,2})|(ectivecoded{1,2})))
…aaaand i’m lost what to do next. how to move on? is there a better compact way to do this?
EDIT: this also means i have to replace ‘dir’ with ‘directive’. it’s implied in the result list, but i didnt’ make a bullet item for it. also, the REGEX is all i was able to build at RegExer. thus the “lost what to do next” part.
Advertisement
Answer
- Match but don’t capture
dir
- Match but don’t capture the optional substring
ective
- Retain zero or more non-digital characters immediately after
ective
as capture group #1 (this accounts for optional substrings likesummarydue
) - Retain the whole integer as capture group #2
- Retain the remainder of the string as capture group #3
- In the custom function, hardcode
directive
, then append capture group #1 (which may be empty), then capture group #3 (might also be empty), finally left pad capture group #2 with a zero to a maximum length of 2-digits and append that value to the end of the string
Code: (Demo)
$strings = [ 'dir1summary', 'dir10summary', 'dir1summarydue', 'dir10summarydue', 'directive1', 'directive10', 'directivecode1', 'directivecode10', ]; var_export( preg_replace_callback( '/dir(?:ective)?(D*)(d+)(.*)/', function ($m) { return "directive{$m[1]}{$m[3]}" . str_pad($m[2], 2, "0", STR_PAD_LEFT); }, $strings ) );
Output:
array ( 0 => 'directivesummary01', 1 => 'directivesummary10', 2 => 'directivesummarydue01', 3 => 'directivesummarydue10', 4 => 'directive01', 5 => 'directive10', 6 => 'directivecode01', 7 => 'directivecode10', )
Alternatively, you could parse the string with sscanf()
, then print the isolated components in the desired format with printf()
.
Code: (Demo)
foreach ($strings as $string) { sscanf($string, '%[^0-9]%d%s', $dir, $num, $str); printf("%s%s%02dn", str_pad($dir, 9, 'ective'), $str, $num); } // same result strings as above