将 bash 命令输出中的子字符串替换为另一个命令的 return 值(例如,将时间戳转换为日期)

Replace substring in bash command output with return value of another command (e.g. turn timestamp into date)

我有一个输出 Unix 时间戳后跟一些文本的命令:

> mycommand
1484169138 happened XYZ
1484169139 happened XZY
...

我想将时间戳转换为人类可读的字符串,但似乎不知道如何做。

我尝试了各种工具(例如 sedawk)。下面的 似乎很接近;但我在 FreeBSD 上,它似乎没有 GNU 扩展可以使用 e:

$ mycommand |sed -E 's#([0-9]{10})#date -r #e'
sed: 1: "s#([0-9]{10})#date -r #e": bad flag in substitute command: 'e'

您可以在 POSIX shell 的 while 循环中使用 date 命令重新格式化日期(我应该指出这可能不是您在 shell 中的默认设置FreeBSD).

$ while read d t; do printf "[%s] %s\n" "$(date -r "$d" '+%F %T')" "$t"; done < x.txt
[2017-01-11 16:12:18] happened XYZ
[2017-01-11 16:12:19] happened XZY

while 循环也可以是管道的结尾:

$ mycommand | while read d t; do ...; done

BSD sed 不支持 GNU-sed-specific /e 选项允许使用 shell 命令在 s 函数调用,如您所见。

但是,awk 可以提供类似的功能:

$ awk '{ ("date -r " ) | getline  } 1' <<'EOF'
1484169138 happened XYZ
1484169139 happened XZY
EOF
Wed Jan 11 16:12:18 EST 2017 happened XYZ
Wed Jan 11 16:12:19 EST 2017 happened XZY
  • ("date -r " ) 从第一个字段构造一个 shell 命令,包含以秒为单位的 Unix 纪元时间,例如 date -r 1484169138,在具有 en-US 东部时区的语言环境产生 Wed Jan 11 16:12:18 EST 2017(请注意 GNU date-r 选项具有完全不同的语义)。

  • ... | getline 执行 shell 命令(通过 sh -c)并在变量 </code> 中捕获命令的标准输出输出;即,它<em>用命令的输出替换</em>第一个字段。</p></li> <li><p><code>1 是一个常见的 shorthand,用于简单地打印手头的(修改后的)记录。