0

I am trying to learn how to write a RegEx but it seems all my searches lead to unclear information. So my question is two fold.

  1. Does anyone have a good source on how a newbie could learn to write RegExs?
  2. How could I write a RegEx that breaks the string 1y 311d 16h 42m into variables?

I'm looking to take the above text string and break it into something like:

$duration[years] = 1;
$duration[days] = 311;
$duration[hours] = 16;
$duration[minutes] = 42;

Please note the total digits might may not always be the same for example it could be two digit days. Something like. 25d or some could be omitted. I might just get days and hours. Lastly the order might change. Perhaps it is written days then years etc.

I know I could do this easily with an explode function and strpos, but I really want to learn Regex so I am using this as an example as I understand they can be very powerful for things like this.

1 Answer 1

2

1) Some useful pages:

2) Specifically, this:

$pattern = '/(?:(?P<years>\d+)y\s*)?(?:(?P<days>\d+)d\s*)?(?:(?P<hours>\d+)h\s*)?(?:(?P<minutes>\d+)m\s*)?/';
preg_match($pattern, '1y 311d 16h 42m', $duration);
print_r($duration);
// Array
// (
//     [0] => 1y 311d 16h 42m
//     [years] => 1
//     [1] => 1
//     [days] => 311
//     [2] => 311
//     [hours] => 16
//     [3] => 16
//     [minutes] => 42
//     [4] => 42
// )
preg_match($pattern, '311d 42m', $duration);
print_r($duration);
// Array
// (
//     [0] => 1y 311d 16h 42m
//     [years] =>
//     [1] =>
//     [days] => 311
//     [2] => 311
//     [hours] =>
//     [3] =>
//     [minutes] => 42
//     [4] => 42
// )

This will give fixed order though. If the order can change, regexp is not a good tool. It's still possible in this case, but rather awkward. Here it is:

$pattern = "/(?=.*?(?:(?P<years>\d+)y|$))(?=.*?(?:(?P<days>\d+)d|$))(?=.*?(?:(?P<hours>\d+)h|$))(?=.*?(?:(?P<minutes>\d+)m|$))/";    
preg_match($pattern, '311d 16h 1y', $duration);
print_r($duration);
// Array
// (
//     [0] =>
//     [years] => 1
//     [1] => 1
//     [days] => 311
//     [2] => 311
//     [hours] => 16
//     [3] => 16
// )

Entering these patterns (without the leading and trailing slashes) in regex101 will give you the explanation of what exactly it is trying to match. Find other examples from the regex tag questions and enter them as well, and try to see how they work. Experience is the best teacher.

Sign up to request clarification or add additional context in comments.

2 Comments

So you can put the array Key directly in the RegEx? What is making it add the extra key with the index number?
The named capture groups are an extension. Normally, capture groups are numeric; PHP's (?P<name>...) will create both a traditional numeric capture as well as the named one. The 0 group is different: it returns the whole matched substring; however, since in the last example everything is done by lookaheads which are null-width assertions, the matched substring is also width 0.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.