我有一个如下所示的文本流:
----------------------------------------
s123456789_9780
heartbeat:test @ 1344280205000000: '0'
heartbeat:test @ 1344272490000000: '0'
这些长数字是以微秒为单位的时间戳。我希望通过某种管道来运行此输出,这些管道会将这些时间戳更改为更易于理解的日期。
我有一个日期命令可以做到这一点,只给出时间戳(使用以下冒号):
$ date --date=@$(echo 1344272490000000: | sed 's/.......$//') +%Y/%d/%m-%H:%M:%S
2012/06/08-10:01:30
我想结束这样的事情:
----------------------------------------
s123456789_9780
heartbeat:test @ 2012/06/08-12:10:05: '0'
heartbeat:test @ 2012/06/08-10:01:30: '0'
我认为sed
不允许我匹配时间戳并将其替换为调用shell函数的值(尽管我希望显示错误)。或许awk
可以做到吗?我对awk
不是很熟悉。
对我来说似乎很棘手的另一部分就是让那些不匹配的行无需修改。
我当然可以编写一个可以执行此操作的Python程序,但是如果可能的话,我宁愿将其保存在shell中(这是在shell脚本中生成的,而我宁愿不依赖于外部文件)。 / p>
答案 0 :(得分:3)
这可能适合你(GNU sed):
sed '/@ /!b;s//&\n/;h;s/.*\n//;s#\(.\{10\}\)[^:]*\(:.*\)#date --date=@\1 +%Y/%d/%m-%H:%M:%S"\2"#e;H;g;s/\n.*\n//' file
说明:
/@ /!b
纾困并打印任何不包含@
后跟空格的行s//&\n/
在上述模式之后插入换行符h
将模式空间(PS)复制到保留空间(HS)s/.*\n//
删除最多并包含@
后跟空格s#\(.\{10\}\)[^:]*\(:.*\)#date --date=@\1 +%Y/%d/%m-%H:%M:%S"\2"#e
来自PS中的剩余部分,对前10个字符进行后向引用,并从:
到字符串末尾。将这些传递到date
命令并将结果评估为PS H
将PS附加到HS,同时插入换行符g
将HS复制到PS s/\n.*\n//
删除字符串的原始部分答案 1 :(得分:1)
我还想看一个sed
解决方案,但它有点超出我的sed
- fu。由于awk
支持strftime
,所以这里非常简单:
awk '
/^ *heartbeat/ {
gsub(".{7}$", "", $3)
$3 = strftime("%Y/%d/%m-%T", $3)
print " ", $1, $3
}
$0 !~ /heartbeat/' file
输出:
s123456789_9780
heartbeat:test 2012/06/08-21:10:05
heartbeat:test 2012/06/08-19:01:30
$3
是微秒字段。 gsub
将时间戳转换为秒。
$0 !~
确保打印非心跳线(隐式{ print }
是默认块)。
答案 2 :(得分:1)
怎么样:
while read s1 at tm s2
do
tm=${tm%000000:}
echo $s1 $at $(date --date @$tm +%Y/%d/%m-%H:%M:%S)
done < yourfile
答案 3 :(得分:1)
使用一点sed进行Bash,保留输入的空白:
while read -r; do
parts=($REPLY)
if [[ ${parts[0]} == "heartbeat:test" ]]; then
dateStr=$(date --date=@${parts[2]%000000:} +%Y/%d/%m-%H:%M:%S)
REPLY=$(echo "$REPLY" | sed "s#[0-9]\+000000:#$dateStr#")
fi
printf "%s\n" "$REPLY"
done
答案 4 :(得分:0)
这主要使用bash
命令在date
内:
#!/bin/bash
IFS=$
while read a ; do
case "$a" in
*" @ "[0-9]*) pre=${a% @ *}
a=${a#$pre @ }
post=${a##*:}
a=${a%??????:$post}
echo "$pre$(date --date=@$a +%Y/%d/%m-%H:%M:%S):$post"
;;
*) echo "$a" ;;
esac
done <<.
----------------------------------------
s123456789_9780
heartbeat:test @ 1344280205000000: '0'
heartbeat:test @ 1344272490000000: '0'
.