我想用Perl正则表达式重新安排时间戳,尽可能减少代码。时间戳的原始格式如下:
2011/12/29 20:19:45
我所需要做的就是转换它,使前面的年份在月份/日期之后,如下所示:
12/29/2011 20:19:45
我能够通过下面的3行代码实现这一点。我只是想知道是否有一种方法可以用更少的代码做到这一点。特别是,我试图取消中间一行,将$1保存到中间变量中,并直接在正则表达式中从第一个替换中指定$1作为第二个替换,但这导致了错误:"在串联(.)或字符串中使用未初始化的值$1。"
如果第二行不能去掉,那么这似乎也不能归结为一行?
#my $ts = '2011/12/29 20:19:45'; #input to a subroutine
$ts =~ s/^(d{4})///;
my $year = $1;
$ts =~ s/ //$year /;
给你:
$ts =~ s|^(d{4})/(d{2})/(d{2})(.+)$|$2/$3/$1$4|;
请注意,上面的表达式要求时间戳的恰好为,月份和天数为2位,年份为4位。但你可以让它更短但更可靠:
$ts =~ s|^(d+)/(d+)/(d+)(.+)$|$2/$3/$1$4|;
这一个将正确处理像1998年1月12日12:34:56这样的时间戳。
使用Back References可以获得所需的格式-
[jaypal:~/Temp] echo "2011/12/29 20:19:45" |
perl -pe 's@([0-9]{4})/([0-9]{2})/([0-9]{2})@$3/$1/$2@'
29/2011/12 20:19:45
对于更通用的时间戳操作,您可能希望通过strptime
/strftime
往返。在这种情况下,这只是字段的重新排序,但对于更复杂的情况,例如将月份编号转换为名称,则需要strftime
。
my @t = strptime "2011/12/29 20:19:45", "%Y/%m/%d %H:%M:%S";
say strftime "%d/%m/%Y %H:%M:%S", @t; # 29/12/2011 20:19:45
say strftime "%d %b %Y, %H:%M:%S", @t; # 29 December 2011, 20:19:45