【问题标题】:Re-arranging a timestamp with a Perl regex使用 Perl 正则表达式重新排列时间戳
【发布时间】:2012-01-20 01:03:34
【问题描述】:

我想用尽可能少的代码用 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 /;

【问题讨论】:

  • 乔治的评论+1。请不要在没有解释的情况下进行降级。这对任何人都没有帮助。

标签: regex perl


【解决方案1】:

给你:

$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 这样的时间戳。

【讨论】:

  • 感谢您的扩展回答,包括对我的“倾斜牙签”的解释和改进
  • 任何时候。顺便说一句,您可以通过将日期和月份组合在一起使正则表达式更短:s|^(\d+)/(\d+/\d+)(.+)$|$2/$1$3| :)
  • 好答案。问题和答案都对我有帮助,适当升级。
  • 我倾向于不将日/月组合在一起,因为有很多不同的日期格式。如果您打算再次在类似的地方使用代码,则将字段分组会更明智。
  • 不需要捕获字符串的其余部分。如果您没有指定要更改,则不会。更短的是s|(\d{4})/(\d+)/(\d+)|$2/$3/$1|;
【解决方案2】:

使用反向引用可以获得所需的格式 -

[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

【讨论】:

  • \3 等最好写成$3
  • 真的......我真的不知道perl 只是使用了它的sed 功能。将更新答案,因为它看起来更好,并感谢您的反馈。 :)
【解决方案3】:

对于更通用的时间戳操作,您可能希望通过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

【讨论】:

    猜你喜欢
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多