我与regex
匹配相当不错,但下面的这个让我在周五下午难倒。我在" date"中有以下3个字符串的变体。我需要发送到MySQL
作为范围的格式,以获取之间的匹配结果。作为背景,数据来自我无法控制的JSON
来源,并且在传递给Perl
之前由MySQL
处理。除了最后一个版本,一切都很好。
要匹配的变体
2014-04-01~2014-04-16
~2014-04-16
2014-04-01~
第一个是范围。第二个是从时间开始到日期,最后一个是从日期到结束时间。
当前正则表达式
/(\d{4}-\d{2}-\d{2})~|~(\d{4}-\d{2}-\d{2})/g;
现在我经历了大量的Regex
组合,所列出的组合仅仅是我与之合作的最后一个组合。
问题是我需要将日期指定为from
和to
。这个很好,因为我有两个日期,因为我有两个捕获组,只有开始时间没关系,因为它自动成为第一个捕获组,但我遇到困难的时候只有#34;从开始时间开始至日期"用于放置在第一个捕获组中,如下所示,我希望它在第二个捕获组中。
Perl中的用法示例
my $date = '~2014-04-01';
my ($f,$t) = $date =~ /(\d{4}-\d{2}-\d{2})/gm;
print "FROM: " . $f . "\n";
print "TO: " . $t . "\n";
我不想在regex
中使用多个perl
模式,并且希望将perl
仅限于上述regex
举重。
在这种情况下,任何人都可以为regex
提供解决方案吗?
答案 0 :(得分:2)
use strict;
use warnings;
while (<DATA>) {
if (/(\d{4}-\d{2}-\d{2})?~(\d{4}-\d{2}-\d{2})?/) {
if (defined $1 && defined $2) {
print "a range <$1> to <$2>\n";
} elsif (defined $1) {
print "a start <$1>\n";
} elsif (defined $2) {
print "a stop <$2>\n";
} else {
print "just a ~, ignore\n";
}
}
}
__DATA__
2014-04-01~2014-04-16
~2014-04-16
2014-04-01~
输出:
a range <2014-04-01> to <2014-04-16>
a stop <2014-04-16>
a start <2014-04-01>
答案 1 :(得分:0)
这是我的解决方案。请注意,我定义了$date
来保存正则表达式的重复部分。我认为这有助于提高可读性。
#!/usr/bin/perl -w
use strict;
use warnings;
my $date = q(\d{4}-\d{2}-\d{2});
my ($from, $to);
while (<DATA>) {
chomp;
if (/^($date)~($date)$|^(~)($date)$|^($date)(~)$/) {
# ^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^
# (1) (2) (3)
($from, $to) = ($1, $2) if defined($1); # pattern (1)
($from, $to) = ($3, $4) if defined($3); # pattern (2)
($from, $to) = ($5, $6) if defined($5); # pattern (3)
print $_, " => [$from][$to]\n";
}
}
__END__
2014-04-01~2014-04-16
~2014-04-16
2014-04-01~
预期输出
2014-04-01~2014-04-16 => [2014-04-01][2014-04-16]
~2014-04-16 => [~][2014-04-16]
2014-04-01~ => [2014-04-01][~]