3v4l.org

run code in 300+ PHP versions simultaneously
<?php $cases = [ 'bar 3 m foo -', '2 s foo +', '222 h baz bar +', 'bass drop 2 d bare -', '2 3 m foo foo -', '1 222 4 d baz -', '2 d 3 m baz +', '5d 4h 3m 2s foo +', '5d 4h 3m 2s', '1 mon foo', '1w bar', '1 month baz', '2 months foobar' ]; function test($cases) { $reg1 = "/ (?<int> (?:\G|(?!\n)) \s*\b \d{1,5} \s* )\K (?<time>(?: s|m(on)?|h|d|w)\b)/uix"; $array = $final = []; foreach($cases as $cas){ $out = preg_replace_callback ($reg1, function($matches){ switch($matches['time']){ case 's': $m = 'sec'; break; case 'm': $m = 'min'; break; case 'h': $m = 'hr'; break; case 'd': $m = 'day'; break; case 'w': $m = 'week'; break; case 'mon': $m = 'month'; break; } return $m; }, $cas); $array[] = $out; $regex = <<<'REGEX' /(?(DEFINE) (?<int> (\s*\b)? (\d{1,5})? (\s*)? ) (?<timepart> (?&int) ( s(ec(ond)?s?)? | m(in(ute)?s?|onths?)? | h(rs?|ours?)? | d(ays?)? | w(eeks?)? ) \b ) ) ^(?<time>(?:(?&timepart)(*SKIP).)+)(?<string>.+)$ /uix REGEX; if(preg_match($regex,$out,$matches)){ $final[] = $matches['time'].$matches['string']; } } return $final; } $output = test($cases); print_r($output);

preferences:
51.44 ms | 2029 KiB | 5 Q