如何将YYYYMMDDHHMMSS转换为可被“date”读取的日期

4
我有一组日期/时间字符串,格式为YYYYMMDDHHMMSS,我想将它们转换成可以被date工具读取的格式。通常情况下,我可以这样做:
date -d "2010-10-01 12:34:56"
然而,date不支持YYYYMMDDHHMMSS格式:
date -d "20100101123456"..invalid date 因此,我可能需要将字符串格式改为先前的格式。我认为sed是答案,但很快就会变得很丑陋。我非常确定我的字符串将是正确的格式,那么如何轻松地将它们转换?

我稍微修改了你的标题。看起来你是想通过“日期”使其可读,而不是通过Bash; Bash不知道任何关于读取日期的内容。 - Cascabel
6个回答

14

date不允许使用"YYYYMMDDHHMMSS"格式,但是它支持"YYYYMMDD HH:MM:SS"格式,因此:

D="20100101123456"
date -d "${D:0:8} ${D:8:2}:${D:10:2}:${D:12:2}"

4
如果格式完全固定,你可以在bash中处理字符串,将其分解为各个部分:
d=20100101123456
pretty_date="${d:0:4}-${d:4:2}-${d:6:2} ${d:8:2}:${d:10:2}:${d:12:2}"
# 2010-01-01 12:34:56
...

我不建议尝试使用正则表达式 - 就像你说的,模式会很快变得难以理解。即使使用扩展或Perl正则表达式,也需要大量重复输入 ([0-9]{4})。或者您可以更加灵活,只匹配 . ;这样可以省略验证。


在 shell 中,格式化可以节省大量时间,并消除管道和外部二进制文件的开销负担。有许多 ${} 转换可用。不要忘记使用 [[ ]],以便测试也在同一空间中运行。 - Mark Stinson

2

为什么这里有那么多关于正则表达式的答案?date(1)工具可以使用strftime()样式的日期格式设置...下面是一个将一个日期类型转换为另一个日期类型的示例:

$ date -j -f "%Y%m%d%H%M%S" "20100101123456" "+%Y-%m-%d %H:%M:%S"
2010-01-01 12:34:56

如果它不是你想要的格式,那么将其转换为所需格式,然后再使用它。如果您只想设置它,则可以简单地执行以下操作:

$ date -f "%Y%m%d%H%M%S" "20100101123456"

3
这适用于BSD,但不适用于GNU。 - Dennis Williamson
所以你是对的...这是一个罕见的情况,GNU工具确实不如其他工具。 - uzi
另一个劣势实例是许可条款。 :) - User1
请注意,读取日期(参见-d选项)不是POSIX日期的一部分。但只要您不在像Solaris这样的发行版上工作(OP已将其标记为Linux而不是Unix),您就应该没问题。 :) 在此处查看我的答案以获取更多细节。 - Cadoiz

2

试试这个:

echo "20101106213245" | sed -r 's/^.{8}/& /;:a; s/([ :])(..)\B/\1\2:/;ta'

结果:

20101106 21:32:45
  • 在第八个字符后插入一个空格
  • [标签a] 在空格或冒号以及下两个字符之后添加冒号
  • 如果进行了替换,请转到标签a

您还需要一些连字符吗?

echo "20101106213245" | sed -r 's/^.{4}/&-/;:a; s/([-:])(..)\B/\1\2:/;ta;s/:/-/;s/:/ /'

结果:

2010-11-06 21:32:45
  • 在第四个字符后插入连字符
  • [标签a] 在连字符或冒号后的下两个字符后添加一个冒号
  • 如果进行了替换,则转到标签a
  • 将第一个冒号更改为连字符(2010-11:06:21:32:45 -> 2010-11-06:21:32:45
  • 将下一个冒号更改为空格(2010-11-06:21:32:45 -> 2010-11-06 21:32:45

1
 sed -ne 's/\(....\)\(..\)\(..\)\(..\)\(..\)\(..\)/\1-\2-\3 \4:\5:\6/p'

我承认这很啰嗦。所有的“.”最好都是[0-9]或\d,尽管我不记得sed是否支持后者。


通常情况下,sed 不支持 Perl 的简写,如 \d\s\t 等,但你可以这样说:d='[0-9]'; sed -ne "s/\\($d$d$d$d\\)\\($d$d\\)\\($d$d\\)\\($d$d\\)\\($d$d\\)\\($d$d\\)"'/\1-\2-\3 \4:\5:\6/p'(请注意双引号强制要求反斜杠需要加倍;你不能使用单引号,因为那样 shell 将不会扩展 $d 的值)。 - tripleee
说实话,我觉得这个比这个更易读,点赞。 - Cadoiz

0

无论是busybox日期还是bsd日期都接受输入格式的描述。

Busybox是一个GNU小型实用程序,易于安装。

bsd格式已在另一个答案中介绍过了,这里介绍busybox:

$ busybox date -D "%Y%m%d%H%M%S" -d "20100101123456" +'%Y-%m-%d %H:%M:%S'
2010-01-01 12:34:56

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接