phpregexzero-padding

PHP REGEX: how to pad numbers in the middle/end of a string


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))|((ective\d{1,2})|(ectivecode\d{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.


Solution


  • 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%02d\n", str_pad($dir, 9, 'ective'), $str, $num);
    }
    // same result strings as above