Reputation: 154
I'm fairly weak on regex and this is giving me a headache to try and figure out. I'm just trying to extract the time from the string and modify the text of the time. I get strings in the following forms:
"Some text I don't care about | 2.3 seconds ago"
"Some text I don't care about | 5.2 minutes ago"
"Some text I don't care about | 7.0 hours ago"
"Some text I don't care about | 1.9 days ago"
I would like to replace the above strings to they are in the forms respectively:
"2.3 secs"
"5.2 mins"
"7.0 hrs"
"1.9 days"
I know basics of replacing in regex, but to remove multiple things in front and behind the text that I want, while replacing "hours" with "hrs", etc is beyond my regex skill level.
Any help would be appreciated.
Thanks.
EDIT:
Well after messing about I came to a solution using multiple different functions. I don't exactly like it, but it works. I would prefer a single preg_replace solution if possible. Here is my current ugly solution:
$testString = "This is text I don't care about | 7.3 seconds ago";
$testString = array_shift(array_reverse(explode('|', $testString)));
$pattern = array('/seconds/', '/minutes/', '/hours/', '/ago/');
$replace = array('secs', 'mins', 'hrs', '');
$testString = trim(preg_replace($pattern, $replace, $testString));
Output is: 7.3 secs
Upvotes: 0
Views: 9541
Reputation: 1216
This is obviously not required any more, but just to show that things like this can be done with one expression if you substitute out all the parts you don't want via alternation.
For example by replacing ^.+\| +|(?:ond|ute|ou)| ago
with the empty string:
$result = preg_replace('/^.+\| +|(?:ond|ute|ou)| ago/', '', $yourData);
See regex demo.
Upvotes: 0
Reputation: 92894
Simple solution using preg_match
and str_replace
functions:
$testString = "This is text I don't care about | 7.3 seconds ago";
$timeUnitsmap = ["secs" => "seconds", "mins" => "minutes", "hrs" => "hours"];
preg_match("/\b[0-9.]+? \w+?\b/i", $testString, $matches);
$testString = str_replace(array_values($timeUnitsmap), array_keys($timeUnitsmap), $matches[0]);
print_r($testString); // "7.3 secs"
Or using preg_replace_callback
and array_search
functions:
...
$testString = preg_replace_callback(["/.*?\b([0-9.]+? )(\w+?)\b.*/"], function($m) use($timeUnitsmap){
return $m[1]. array_search($m[2], $timeUnitsmap);
}, $testString);
Upvotes: 0
Reputation: 56
preg_replace
has an optional 4th parameter which is a limit.
The limit is the maximum amount of matches it can replace.
Php preg_replace
it is automatically global, which means it will replace all matches unless you put a positive number for the limit.
http://php.net/manual/en/function.preg-replace.php
Upvotes: 0
Reputation: 1873
If you really want your search/replace on one line, you can do something like this:
$time_map = array(
'seconds' => 'secs',
'minutes' => 'mins',
'hours' => 'hrs',
'days' => 'days',
);
$data = array(
"Some text I don't care about | 2.3 seconds ago",
"Some text I don't care about | 5.2 minutes ago",
"Some text I don't care about | 7.0 hours ago",
"Some text I don't care about | 1.9 days ago",
);
foreach ($data as $line) {
$time_data = preg_replace_callback("/(.*|\s*)([0-9]+\.[0-9]+) (\w+) ago/", function ($matches) use ($time_map) {return $matches[2] . " " . $time_map[$matches[3]];}, $line);
print "$time_data\n";
}
Which produces:
2.3 secs
5.2 mins
7.0 hrs
1.9 days
Upvotes: 2