如何使用 sed 将纪元转换为人类可读的日期时间

Posted

技术标签:

【中文标题】如何使用 sed 将纪元转换为人类可读的日期时间【英文标题】:How to use sed to convert epoch to human readable date time 【发布时间】:2021-06-28 08:03:23 【问题描述】:

我尝试使用 sed/e 选项调用 date -d @ 将纪元转换为人类可读的日期时间,但似乎 sed 仅在输入行时才有效很简单

我准备了一个 bash 文件来简单地将纪元转换为我的格式并将其复制到 usr/local/bin 中,它在我的 $PATH

#!/bin/bash
date +'%Y-%m-%d %T %Z' -d @$1

我可以证明它工作正常:

$ echo 1616720904 | sed 's/\(.*\)/epoch-to-date \1/e'
2021-03-26 02:08:24 CET

但是:

    如果您像往常一样从日志文件中输入复杂的字符串,则它不起作用:
$ echo "timestamp:1616720904" | sed 's/\(timestamp\:\)\([0-9]*\)/`epoch-to-date \2`/e'
sh: 1: 2021-03-26: not found

如您所见,2021-03-26 是转换后的日期时间的一部分,似乎再次传递给 bash sh: .... not found

    如果输入字符串中有更多文本,它会将所有文本传递给 bash:
$ echo "version:123,timestamp:1616720904" | sed 's/\(timestamp\:\)\([0-9]*\)/`epoch-to-date \2`/e'
sh: 1: version:123,2021-03-26: not found

我会得到的输出是:

version:123,timestamp:2021-03-26 02:08:24 CET

【问题讨论】:

【参考方案1】:

我的建议是从您的字符串中提取纪元,然后在结果上调用 epoch-to-date:

for s in 1616720904 timestamp:1616720904 version:123,timestamp:1616720904
do
  epoch-to-date "$(echo "$s" | sed 's/version:[0-9]\+,//; s/timestamp://')"
done

【讨论】:

【参考方案2】:

不要将e 选项与sed 一起使用——大多数时候它会让人很困惑。在您的情况下,只需:

<<<version:123,timestamp:1616720904 sed 's/.*timestamp:\([0-9]*\)/\1/' | xargs epoch-to-date 

【讨论】:

【参考方案3】:

    失败的原因不是输入字符串的复杂性,而只是与工作正常的示例相反,您将命令放在``,这会导致它的输出被解释为命令。只需省略` `

    这里也一样。除此之外,要删除输入字符串中的更多文本,请通过将时间戳之前的文本包含在搜索模式中来满足它:

    <<<version:123,timestamp:1616720904 sed 's/.*timestamp:\([0-9]*\)/epoch-to-date \1/e'
    

    (我还删除了对不需要的文本的不必要捕获。) 如果时间之后还有更多的文字,也需要这样做。

但是如何用转换后的纪元打印出源输入字符串呢?

确实,我们需要` `

<<<version:123,timestamp:1616720904 sed 's/\(.*timestamp:\)\([0-9]*\)/echo \1`epoch-to-date \2`/e'

【讨论】:

是的,我明白了。但是如何用转换后的纪元打印出源输入字符串呢?删除epoch-to-date 的不必要文本我将丢失部分输入字符串 你的意思是,打印version:123,timestamp:2021-03-26 02:08:24 CET? - 啊,对不起,我刚刚意识到你的意思是 我会得到的输出是:. 谢谢!您的最后一个建议非常有效。【参考方案4】:

感谢我所做的每个人epoch-to-date 我想分享的实用程序:

#!/bin/bash
if [ -f $1 ]; then
    #echo is_file
    #looks for 10 digits number within the line and try to convert it
    cat $1 | sed 's/\(.*\)\([0-9]\10\\)\(.*\)/echo \1`epoch-to-date \2`\3/e'
else
    #echo is_epoch
    date +'%Y-%m-%d %T %Z' -d @$1
fi

将此文件复制到您的主目录中,使其可执行并从 /usr/local/bin 或 $PATH 中的其他目录链接它

sudo chmod +x epoch-to-date
cd /usr/local/bin
sudo ln -s /home/<your_name>/epoch-to-date

用法:

$ epoch-to-date 1616720904
2021-03-26 02:08:24 CET

或一次转换整个日志文件:

$ cat file.log
EP_REQ/GZ200101 "cmd":"Reboot","mode":"HW","hw_ver":"1.02","fw_ver":"1.2.3","cfg_ver":"0","timestamp":1616720904

$ epoch-to-date file.log
EP_REQ/GZ200101 cmd:Reboot,mode:HW,hw_ver:1.02,fw_ver:1.2.3,cfg_ver:0,timestamp:2021-03-26 02:08:24 CET

$ cat file.log | epoch-to-date
EP_REQ/GZ200101 cmd:Reboot,mode:HW,hw_ver:1.02,fw_ver:1.2.3,cfg_ver:0,timestamp:2021-03-26 02:08:24 CET

【讨论】:

【参考方案5】:

这可能对你有用(GNU sed 和 bash):

echo "etd() date +'%F %T %Z' -d@\$1; " >funlib
val="version:123,timestamp:1616720904"
<<<"$val" sed -E 's/(.*:)(.*)/bash -c '\''. funlib;echo "\1$(etd \2)"'\''/e'

将函数etd写入一个名为funlib的文件。

将字符串version:123,timestamp:1616720904赋值给变量val

使用这里字符串&lt;&lt;&lt; 模式匹配$val 的两个部分,然后使用替换命令的e 标志,调用bash 中的两个命令来获取funlib 文件,然后调用内部函数以获取 etd 函数的结果,使用替换命令的 LHS 中的第二个反向引用作为唯一参数,并将结果回显。

注意sed 评估的默认 shell 硬编码为 /bin/sh,这通常是对 dash 的符号引用,因此如果需要,需要显式调用 bash

【讨论】:

以上是关于如何使用 sed 将纪元转换为人类可读的日期时间的主要内容,如果未能解决你的问题,请参考以下文章

将纪元转换为人类可读的日期在 python 中不起作用

在 Mac OSX 上将 unix 纪元时间转换为人类可读的日期 - BSD

在mysql中将纪元数转换为人类可读的日期

将人类可读的日期转换为纪元时间戳

如何将此特定的 varchar 转换为人类可读的日期格式?

bash将csv尾部的纪元时间转换为人类可读