0

Search in the array for the first occurrence of a string until space, then convert it to month.

$arr = [
 "May Hello",
 "Jun Hello12",
 "Jul 3"
];

$str =  $arr[0];
$matches = [];
$pattern = '/^\w+\s/';
preg_match_all($pattern, $str, $matches);

Replace $pattern in $arr:

$pattern = [
 '/^\w+\s/' => date('m', strtotime($matches[0][0])) . ' ', // fist string until space
];
$arr = preg_replace(array_keys($pattern), array_values($pattern), $arr);

echo '<pre>';
print_r($arr);
echo '</pre>';

unexpected:

Array
(
    [0] => 05 7 Hello
    [1] => 05 Hello12
    [3] => 05 3
)

expected:

Array
(
    [0] => 05 7 Hello
    [1] => 06 Hello12
    [3] => 07 3
)

What am I doing wrong?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Cem Firat
  • 390
  • 2
  • 21
  • Topical: [calling function inside preg_replace thats inside a function](https://stackoverflow.com/q/2082207/2943403) and [PHP preg_replace() backreferences used as arguments of another function](https://stackoverflow.com/q/1204668/2943403) and [How to call a function within preg_replace()?](https://stackoverflow.com/q/45554259/2943403) and [Trying to call a function inside preg_replace](https://stackoverflow.com/q/43333590/2943403) and [PHP preg_replace with references passed to functions](https://stackoverflow.com/q/22753232/2943403) – mickmackusa Jan 16 '23 at 22:15
  • and [php converting preg_replace to preg_replace_callback](https://stackoverflow.com/q/35279603/2943403) and [Using each match in preg_replace() in PHP](https://stackoverflow.com/q/35690583/2943403) and [preg_replace which uses the return value of function as replacement](https://stackoverflow.com/q/6221126/2943403) and [Replace with dynamic variable in preg_replace](https://stackoverflow.com/q/51947388/2943403) and [PHP:preg_replace function](https://stackoverflow.com/q/18018265/2943403) – mickmackusa Jan 16 '23 at 22:19
  • and [How to use preg_replace in php to replace text with function result?](https://stackoverflow.com/q/7461264/2943403) and [Replace preg_replace() e modifier with preg_replace_callback](https://stackoverflow.com/q/15454220/2943403) and [Using PHP preg_replace match result in a math operation?](https://stackoverflow.com/q/54400328/2943403) and [Is it possible to have logic in PHP's preg_replace function's replace parameter?](https://stackoverflow.com/q/64136325/2943403) – mickmackusa Jan 16 '23 at 22:24

3 Answers3

2

You should use preg_replace_callback when you want to run a function on the matched results:

$arr = [
 "May Hello",
 "Jun Hello12",
 "Jul 3"
];

$arr = preg_replace_callback(
        '/^(\w+)\s/',
        function ($matches) {
            return date('m', strtotime($matches[0])).' ';
        },
        $arr
    );

echo '<pre>';
print_r($arr);
echo '</pre>';

Output:

Array
(
    [0] => 05 Hello
    [1] => 06 Hello12
    [2] => 07 3
)
cOle2
  • 4,725
  • 1
  • 24
  • 26
2

Use a word boundary in the pattern to ensure that only a 3-letter word is found at the start of the string. In the closure, you can convert the fullstring match to its zero-padded month number and omit the concatenation of a trailing space.

Code: (Demo)

var_export(
    preg_replace_callback('/^[A-Z][a-z]{2}\b/', fn($m) => date('m', strtotime($m[0])), $arr)
);

For better processing economy, you can keep a cache of translated month values to avoid calling two functions (or instantiating a datetime object and calling a method) to generate replacement strings each time. The closure becomes a little more verbose though. (Demo)

var_export(
    preg_replace_callback(
        '/^[A-Z][a-z]{2}\b/',
        function($m) {
            static $trans = [];
            $trans[$m[0]] ??= date('m', strtotime($m[0])); // only assign / call functions if needed
            return $trans[$m[0]];
        },
        $arr
    )
);

Depending on your input strings, if the letters of the 3-letter month are guaranteed to not occur later in the string then you can create a translation array and call strtr() to avoid regex. (Demo)

$trans = [
    'Jan' => '01',
    'Feb' => '02',
    'Mar' => '03',
    'Apr' => '04',
    'May' => '05',
    'Jun' => '06',
    'Jul' => '07',
    'Aug' => '08',
    'Sep' => '09',
    'Oct' => '10',
    'Nov' => '11',
    'Dec' => '12'
];

foreach ($arr as $v) {
    echo strtr($v, $trans) . "\n";
}
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0
    $len = count($arr);

    for ($i=0; $i<$len; $i++) {
        $element = $arr[$i];
        $letterMonth = substr($element, 0, 3);
        $dateObj = \DateTime::createFromFormat('F', $letterMonth);
        $month = $dateObj->format('m');
        $arr[$i] = str_replace($letterMonth, $month, $element );
    }

    return $arr;
usrobotics
  • 64
  • 3
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 19 '23 at 14:17