Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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";
like image 533
ncowboy Avatar asked Mar 20 '13 02:03

ncowboy


People also ask

How do I match a pattern in Perl?

m operator in Perl is used to match a pattern within the given text. The string passed to m operator can be enclosed within any character which will be used as a delimiter to regular expressions.

What is \b in Perl regex?

The metacharacter \b is an anchor like the caret and the dollar sign. It matches at a position that is called a “word boundary”. This match is zero-length. There are three different positions that qualify as word boundaries: Before the first character in the string, if the first character is a word character.

What does (?: Mean in regex?

(?:...) A non-capturing version of regular parentheses. Matches whatever regular expression is inside the parentheses, but the substring matched by the group cannot be retrieved after performing a match or referenced later in the pattern.

How do I print a pattern in Perl?

print operator in Perl is used to print the values of the expressions in a List passed to it as an argument. Print operator prints whatever is passed to it as an argument whether it be a string, a number, a variable or anything. Double-quotes(“”) are used as a delimiter to this operator.


2 Answers

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);
like image 132
Sinan Ünür Avatar answered Nov 14 '22 23:11

Sinan Ünür


Which version of Perl are you using? It works for me in 5.8.8 (but not 5.004) if you change it to this:

use constant REGEXP1 => qr/^\d{4}\D\d{2}\D\d{2}\D\d{2}\D\d{2}\D\d{2}\D\d{3}$/;
like image 30
Nick P Avatar answered Nov 15 '22 01:11

Nick P