Найдите в массиве первое вхождение строки до пробела, а затем преобразуйте его в месяц.
$arr = [
"May Hello",
"Jun Hello12",
"Jul 3"
];
$str = $arr[0];
$matches = [];
$pattern = '/^\w+\s/';
preg_match_all($pattern, $str, $matches);
Замените $pattern в $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>';
непредвиденный:
Array
(
[0] => 05 7 Hello
[1] => 05 Hello12
[3] => 05 3
)
ожидал:
Array
(
[0] => 05 7 Hello
[1] => 06 Hello12
[3] => 07 3
)
Что я делаю не так?






Вы должны использовать preg_replace_callback, когда хотите запустить функцию для совпадающих результатов:
$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>';
Выход:
Array
(
[0] => 05 Hello
[1] => 06 Hello12
[2] => 07 3
)
Используйте границу слова в шаблоне, чтобы убедиться, что в начале строки находится только слово из 3 букв. В замыкании вы можете преобразовать совпадение полной строки в номер месяца, дополненный нулями, и опустить конкатенацию завершающего пробела.
Код: (Демо)
var_export(
preg_replace_callback('/^[A-Z][a-z]{2}\b/', fn($m) => date('m', strtotime($m[0])), $arr)
);
Для большей экономии обработки вы можете сохранить кэш переведенных значений месяца, чтобы избежать вызова двух функций (или создания экземпляра объекта datetime и вызова метода) для создания строк замены каждый раз. Однако закрытие становится немного более подробным. (Демо )
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
)
);
В зависимости от ваших входных строк, если буквы месяца из 3 букв гарантированно не встречаются позже в строке, вы можете создать массив перевода и вызвать strtr(), чтобы избежать регулярного выражения. (Демо )
$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";
}
Второй вариант также может использоваться для кратких названий месяцев, отличных от английского.
$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;
Как сейчас написано, ваш ответ неясен. Пожалуйста, отредактируйте , чтобы добавить дополнительные сведения, которые помогут другим понять, как это отвечает на заданный вопрос. Вы можете найти больше информации о том, как писать хорошие ответы в справочном центре.
Актуально: вызов функции внутри preg_replace, которая находится внутри функции и обратные ссылки PHP preg_replace() используются в качестве аргументов другой функции и Как вызвать функцию внутри preg_replace()? и Попытка вызвать функцию внутри preg_replace и PHP preg_replace со ссылками, переданными в функции