如何使用 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
。
使用这里字符串<<<
模式匹配$val
的两个部分,然后使用替换命令的e
标志,调用bash
中的两个命令来获取funlib
文件,然后调用内部函数以获取 etd
函数的结果,使用替换命令的 LHS 中的第二个反向引用作为唯一参数,并将结果回显。
注意sed 评估的默认 shell 硬编码为 /bin/sh
,这通常是对 dash
的符号引用,因此如果需要,需要显式调用 bash
。
【讨论】:
以上是关于如何使用 sed 将纪元转换为人类可读的日期时间的主要内容,如果未能解决你的问题,请参考以下文章