我正在尝试使用哈希将201302_1
形式的字符串转换为2013-02-09
。不幸的是,我对Perl的了解相当有限,我还没有完成它的工作。
BEGIN {
use strict;
use warnings;
use 5.010;
my %cycle = qw (
1 '09' 2 '12' 3 '12' 4 '18' 5 '21'
6 '24' 7 '27' 8 '01' 9 '03' 10 '06'
);
}
s/(\d{4})(\d{2})_(\d+)$/$1-$2-$cycle{$3}/g
如果此脚本还解决了在$2
为8,9或10时添加1个月(增加$1
并最终$3
)的问题,那就太棒了。
我从终端运行perl -p script.pl sample.txt
编辑:我最后根据似乎有用的答案编写了以下内容:
my %cycle = qw (
1 09 2 12 3 12 4 18 5 21
6 24 7 27 8 01 9 03 10 06
);
s{(\d{4})(\d{2})_(\d+)1\.csv$}{
my @r = (undef, $1, $2, $3);
if ($3 > 7) {
$r[2] = sprintf("%02d", $r[2]+1);
}
if ($r[2] > 12) {
$r[2] = "01";
$r[1] = $r[1] + 1;
}
"$r[1]-$r[2]-$cycle{$r[3]}";
}ge;
答案 0 :(得分:4)
您的严格和警告仅限于BEGIN块,因此您没有看到结果的警告,因为%cycle 也仅作用于开始块,而另一个(空)%循环哈希实际上用于替换。
尝试
use strict;
use warnings;
use 5.010;
my %cycle;
BEGIN {
%cycle = ...
由于您计划调整月份和年份,我会避免替换,而是执行:
my ($year, $month, $cycle) = /\A(\d{4})(\d{2})_(\d+)\z/ or die "bad input: $_\n";
my $day = $cycle{$cycle};
if ( $cycle >= 8 ) { # or have a second hash that indicates "following month"
答案 1 :(得分:2)
使用正则表达式解决日期数学通常不是一个好主意,因为它相当复杂并且充满了边缘情况。请改用Time::Piece
:
use strict;
use warnings;
use Time::Piece;
my %cycle = qw (
1 09 2 12 3 12 4 18 5 21
6 24 7 27 8 01 9 03 10 06
);
while (<DATA>) {
chomp;
s/_(\d+)$/$cycle{$1}/;
my $t = Time::Piece->strptime($_, "%Y%m%d");
$t = $t->add_months(1);
print $t->strftime("%Y-%m-%d");
}
__DATA__
201302_1
我已经猜到(因为你没有说)%cycle
中的值是天,因此可以像天一样对待。因此,我们只需使用哈希中的“日期”替换数字,然后使用strptime
解析日期,添加一个月,然后使用strftime
打印日期。
请注意,此代码假定整个字符串是日期,因此您可能需要调整它以用于其他类型的输入。
另请注意,您可以将<DATA>
更改为<>
以像以前一样使用脚本,但不使用-p
开关,即:
perl script.pl sample.txt
答案 2 :(得分:0)
use strict;
use warnings;
use 5.010;
use DateTime;
my $input = $ARGV[0];
my %cycle2day = ( 1 => 9, 2 => 12, 3 => 12, 4 =>18, 5 => 21,
6 => 24, 7 => 27, 8 => 1, 9 => 3, 10 => 6,
);
my ($year, $month, $cycle) = $input =~ /(\d{4})(\d{2})_(\d+)/;
unless (grep { $cycle == $_ } keys %cycle2day) {
die "Unknown cycle $cycle!";
}
my $date = DateTime->new( year => $year,
month => $month,
day => $cycle2day{$cycle},
);
if ( $cycle == 8 or $cycle == 9 or $cycle == 10 ) {
$date->add(months => 1);
}
say $date->ymd;
输出:
C:\>perl test_cycle.pl 201302_1
2013-02-09
C:\>perl test_cycle.pl 201302_9
2013-03-03