The only problem I can see with your own code is that the hours field is optional (because you use a *
) but you don't say what issues you're having.
You do have a lot of unnecessary captures. Every part of the pattern that is enclosed in parentheses will capture the corresponding part of the target string in an internal variables called $1
, $2
etc. Unless you really need those captures it is best to use non-capturing parentheses (?: ... )
instead of the plain ones ( ... )
.
Character classes like [1-9]
are a single entity and don't need enclosing in parentheses. You also haven't accounted for a leading zero on values less than ten, and you should use a character class [AP]
instead of an alternation (?:A|P)
It looks like you need
/\d{1,2}[AP]M/i
But you don't say what you want to do with the times once you have found them.
This snippet of code demonstrates the functionality by putting all the times that it finds in a string into array @times
and then printing it with space separators.
use strict;
use warnings;
for my $string (qw/ 9AM 9AM5PM 09AM05PM /) {
my @times = $string =~ /\d{1,2}[AP]M/ig;
print "@times\n";
}
output
9AM
9AM 5PM
09AM 05PM
If you really want to verify that the hour value is in range (are you likely to come across 35pm
?) then you could write
my @times = $string =~ / (?: 1[012] | 0?[1-9] ) [AP]M /igx
Note that the /x
modifier makes whitespace insignificant within regular expressions, so that it can be used to clarify the form of the pattern.