我想将通用文本文件中的 Unix 纪元(以毫秒为单位)更改为正常日期。我接受 bash、sed、awk 或 perl 解决方案。
示例 file1(只有 13 位数字才是日期):
Foo bar 1397497040418 foo 1526 bar foobar, bar 1397497060518.
Bar, 1357407040418 foo 10 foobar.
我想要这个输出:
Foo bar 2014-04-14 19:37:20 foo 1526 bar foobar, bar 2014-04-14 19:37:40.
Bar, 2013-01-05 18:30:40 foo 10 foobar.
我尝试失败:
sed -E "s/([0-9]{10})/date -d @\1/;e" file1
任何想法?
谢谢。
答案1
使用您的输入文件:
perl -MTime::Piece -pe '
s{ \b (\d{10}) \d{3}\b }
{ localtime($1)->strftime("%F %T") }xge
' file1
Foo bar 2014-04-14 13:37:20 foo 1526 bar foobar, bar 2014-04-14 13:37:40.
Bar, 2013-01-05 12:30:40 foo 10 foobar.
答案2
假设您希望我们忽略额外的数字并将日期转换限制为仅前 10 个数字,这意味着该日期不是未来数十万年,您可以使用 GNU 来执行此date
操作perl
:
$ perl -pe 's/\b(\d{10})\d{3}\b/chomp($i=`date -d \@$1 "+%F %T"`);$i/eg' file1
Foo bar 2014-04-14 18:37:20 foo 1526 bar foobar, bar 2014-04-14 18:37:40.
Bar, 2013-01-05 17:30:40 foo 10 foobar.
格伦的解决方案然而,更干净、更便携,所以如果您不介意使用 perl 模块(而且您不应该),我会推荐他的而不是我的。
至于你的sed
尝试,为了使用结果对于命令,您需要使用反引号或$(command)
.所以你就快到了:
$ sed -E "s/([0-9]{10})/$(date -d @\1)/" file1
Foo bar Thu 01 Jan 1970 01:00:01 AM BST418 foo 1526 bar foobar, bar 1397497060518.
Bar, Thu 01 Jan 1970 01:00:01 AM BST418 foo 10 foobar.
当然,这不会删除多余的数字,也不会将其限制为只有 13 位数字,但由于您还没有明确您需要什么,所以我不知道如何修复它。我的 Perl 解决方案可以处理它,因此如果您不想删除它们,可以使用 sed。
答案3
使用awk
带有match()
,substr()
和strftime()
函数的 GNU。扫描给定行以识别具有 10 个或更多数字的记录,因为它们是 EPOCH 时间戳。
在这些记录上仅提取前 10 位数字并将其传递给strftime()
函数并根据需要应用日期格式。使用该函数将原始记录替换为新时间戳sub()
。
awk '
{
for(col=1; col<=NF; col++) {
if ( match($col, /[[:digit:]]{10,}/) ) {
sub( substr($col, RSTART, RLENGTH),
strftime("%Y-%m-%d %H:%M:%S", substr($col, RSTART, RLENGTH-3) ) )
}
}
}1' file1
答案4
对于时间函数的 GNU awk,match() 的第三个参数和字边界:
$ awk '{
while ( match($0,/(.*)\<([0-9]{10})[0-9]{3}\>(.*)/,a) ) {
$0 = a[1] strftime("%F %T",a[2]) a[3]
}
print
}' file
Foo bar 2014-04-14 12:37:20 foo 1526 bar foobar, bar 2014-04-14 12:37:40.
Bar, 2013-01-05 11:30:40 foo 10 foobar.