How can I define a regexp pattern as a constant in Perl?

datetime, perl, regex

Solution

First, let's look at `"/^\d{4}\D\d{2}\D\d{2}\D\d{2}\D\d{2}\D\d{2}\D\d{3}$/";` If you had warnings on, you should have gotten:

Unrecognized escape \d passed through at C:\temp\jj.pl line 7.
Unrecognized escape \D passed through at C:\temp\jj.pl line 7.
Unrecognized escape \d passed through at C:\temp\jj.pl line 7.
…

If you print the value of `REGEXP1`, you will get `/^d{4}Dd{2}Dd{2}Dd{2}Dd{2}Dd{2}Dd{3}` (*wait, what happened to `$/`?). Clearly, that does not look like the pattern you wanted.

Now, you could type `"/^\\d{4}\\D\\d{2}\\D\\d{2}\\D\\d{2}\\D\\d{2}\\D\\d{2}\\D\\d{3}\$/"` and then interpolate that string into a pattern, but that's too much work. Instead, you can define your constant using the regexp quote operator, `qr`:

#!/usr/bin/env perl

use 5.012;
use strict;
use warnings;

use constant REGEXP1 => qr/^\d{4}\D\d{2}\D\d{2}\D\d{2}\D\d{2}\D\d{2}\D\d{3}$/;

my $s = "2013-03-20 11:09:30.788";

say $s =~ REGEXP1 ? 'yes' : 'no';

There is one more gotcha: `\d` and `\D` will match more than just `[0-9]` and `[^0-9]`, respectively. So, instead, you could write your pattern like:

use constant REGEXP1 => qr{
    \A
    (?<year>  [0-9]{4} ) -
    (?<month> [0-9]{2} ) -
    (?<day>   [0-9]{2} ) [ ]
    (?<hour>  [0-9]{2} ) :
    (?<min>   [0-9]{2} ) :
    (?<sec>   [0-9]{2} ) [.]
    (?<msec>  [0-9]{3} )
    \z
}x;

But, you are still left with the question of whether those values are meaningful. If that matters, you can use DateTime::Format::Strptime.

#!/usr/bin/env perl

use 5.012;
use strict;
use warnings;

use DateTime::Format::Strptime;

my $s = "2013-03-20 11:09:30.788";

my $strp = DateTime::Format::Strptime->new(
    pattern => '%Y-%m-%d %H:%M:%S.%3N',
    on_error => 'croak',
);

my $dt = $strp->parse_datetime($s);
say $strp->format_datetime($dt);

Problem

i want to define a regexp constant in my script at the top and use it later to check the date string's format. my date string will be defined as $a="2013-03-20 11:09:30.788"; but it failed. how should i do ? ``` use strict; use warnings; use constant REGEXP1 => "/^\d{4}\D\d{2}\D\d{2}\D\d{2}\D\d{2}\D\d{2}\D\d{3}$/"; $a="2013-03-20 11:09:30.788"; if(not $a=~&REGEXP1){ print "not" }else{ print "yes" } print "\n"; ```

Original source