我想用尽可能少的代码重新安排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 /;
答案 0 :(得分:5)
你去吧:
$ts =~ s|^(\d{4})/(\d{2})/(\d{2})(.+)$|$2/$3/$1$4|;
请注意,上面的表达式要求时间戳为完全 2位数字表示月份和日期,4位数字表示年份。但是你可以让它更短更可靠:
$ts =~ s|^(\d+)/(\d+)/(\d+)(.+)$|$2/$3/$1$4|;
这个会正确处理时间戳,如1/12/98 12:34:56。
答案 1 :(得分:1)
使用后退参考,您可以获得所需的格式 -
[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
答案 2 :(得分:0)
对于更通用的时间戳操作,您可能希望通过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