Попробуйте сопоставить форматы по очереди. Регулярное выражение ниже соответствует любому из ваших разрешенных разделителей (/
, .
или -
), а затем требуется тот же разделитель через обратную ссылку (10 или \3
). В противном случае у вас есть три возможных разделителя раз в два возможных положения за год, чтобы сделать шесть альтернатив в вашем шаблоне.
#! /usr/bin/env perl
use strict;
use warnings;
#array values may vary in every run
my @dates = ("Mon 11/20/2012","2012.11.20","20-11-2012");
my $date_pattern = qr<
\b # begin on word boundary
(
(?: [0-9][0-9] ([-/.]) [0-9][0-9] \2 [0-9][0-9][0-9][0-9])
| (?: [0-9][0-9][0-9][0-9] ([-/.]) [0-9][0-9] \3 [0-9][0-9])
)
\b # end on word boundary
>x;
foreach my $date (@dates) {
if (my($match) = $date =~ /$date_pattern/) {
print "Date: $match\n";
}
}
Выход:
Date: 11/20/2012
Date: 2012.11.20
Date: 20-11-2012
На моей первой попытки в коде выше, я имел \2
в альтернативе YYYY-MM-DD, где я должен был \3
, которые не смогли соответствовать. Чтобы избавить нас от круглых скобок, version 5.10.0 added named capture buffers.
Это теперь можно назвать захват скобка в шаблоне и относятся к содержимому перехваченных по имени. Синтаксис именования: (?<NAME>....)
. Возможно обращение к именованному буфере с синтаксисом \k<NAME>
. В коде новые магические хэши %+
и %-
могут использоваться для доступа к содержимому буферов захвата.
Используя эту удобную функцию, код выше становится
#! /usr/bin/env perl
use 5.10.0; # named capture buffers
use strict;
use warnings;
#array values may vary in every run
my @dates = ("Mon 11/20/2012","2012.11.20","20-11-2012");
my $date_pattern = qr!
\b # begin on word boundary
(?<date>
(?: [0-9][0-9] (?<sep>[-/.]) [0-9][0-9] \k{sep} [0-9][0-9][0-9][0-9])
| (?: [0-9][0-9][0-9][0-9] (?<sep>[-/.]) [0-9][0-9] \k{sep} [0-9][0-9])
)
\b # end on word boundary
!x;
foreach my $date (@dates) {
if ($date =~ /$date_pattern/) {
print "Date: $+{date}\n";
}
}
и производит тот же результат.
В приведенном выше коде еще много повторений. Используя специальный корпус (DEFINE)
в сочетании с именованными захватами, мы можем сделать рисунок намного приятнее.
#! /usr/bin/env perl
use 5.10.0;
use strict;
use warnings;
#array values may vary in every run
my @dates = ("Mon 11/20/2012","2012.11.20","20-11-2012");
my $date_pattern = qr!
\b (?<date> (?&YMD) | (?&DMY)) \b
(?(DEFINE)
(?<SEP> [-/.])
(?<YYYY> [0-9][0-9][0-9][0-9])
(?<MM> [0-9][0-9])
(?<DD> [0-9][0-9])
(?<YMD> (?&YYYY) (?<sep>(?&SEP)) (?&MM) \k<sep> (?&DD))
(?<DMY> (?&DD) (?<sep>(?&SEP)) (?&MM) \k<sep> (?&YYYY))
)
!x;
foreach my $date (@dates) {
if ($date =~ /$date_pattern/) {
print "Date: $+{date}\n";
}
}
Да, подшаблон имени DMY также соответствует дате в формате MDY. На данный момент этого достаточно, и you ain’t gonna need it.
Не существует (допустимой) причины не использовать модули. Существуют также основные модули, которые обрабатывают время. – TLP
@TLP Это ограничение на моей стороне. Я не могу установить модуль на cygwin Perl, так как я не владею разрешением. Для переупаковки cygwin Perl потребуется несколько месяцев/лет. Я просто хочу, чтобы сценарий был доступен как можно скорее. На самом деле это просто осложнение на моей стороне. – quinekxi
Ваш код работает так, как ожидалось! С чем вы столкнулись? –