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?
CodePudding user response:
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
)
CodePudding user response:
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)
);
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";
}