如何在 sed 中对 \1 进行操作(或在 awk 中对 $1 进行操作)?

如何在 sed 中对 \1 进行操作(或在 awk 中对 $1 进行操作)?

我有包含几行的文件。每个都有一个时间戳,后跟文本:

1534888050 some text
1534888051 some more text
1534888052 text

...并且想要将时间戳转换为可读格式,同时保留文本。结果应为:

Tue Aug 21 21:47:30 UTC 2018 some text
Tue Aug 21 21:47:31 UTC 2018 some more text
Tue Aug 21 21:47:32 UTC 2018 text

date -d@"${somedate}"正确转换时间戳本身。

现在我想要通过一个过滤器/管道命令实现相同的效果sed或者awk(或任何其他常见命令)。

这不起作用,但大致解释了我的想法:

echo '1534888050 some text' | sed "s#^\([0-9]*\) .*#`date -d@\1`#g"

(这\1是匹配的时间戳)

有什么方法可以优雅地实现这一点吗?

答案1

日期工具软件包非常适合此类事情,特别是dconv工具。 (当安装在 Ubuntu 系统上时,该命令可用作dateutils.dconv。)

这是一个例子:

$ cat testfile.txt 
1534888050 some text
1534888051 some more text
1534888052 text
$ dateutils.dconv -i '%s' -f '%a %b %d %T %Y' -S <testfile.txt 
Tue Aug 21 21:47:30 2018 some text
Tue Aug 21 21:47:31 2018 some more text
Tue Aug 21 21:47:32 2018 text
$ dateutils.dconv -i '%s' -f '%F %T' -S <testfile.txt 
2018-08-21 21:47:30 some text
2018-08-21 21:47:31 some more text
2018-08-21 21:47:32 text
$ 

旗帜-S是关键;它告诉工具在“sed 模式”下运行并在输出中包含非日期文本。

-i标志指定输入日期格式,该-f标志指定输出日期格式。

答案2

如果您有 GNU awk (又名gawk),您可以使用其内置strftime函数将纪元时间转换为您选择的格式:

$ TZ=UTC gawk '{$1 = strftime("%a %b %d %H:%M:%S %Z %Y", $1)} 1' file
Tue Aug 21 21:47:30 UTC 2018 some text
Tue Aug 21 21:47:31 UTC 2018 some more text
Tue Aug 21 21:47:32 UTC 2018 text

您还可以将 perl 与POSIX模块一起使用:

$ TZ=UTC perl -MPOSIX -alne '
    print join " ", strftime("%a %b %d %H:%M:%S %Z %Y", localtime shift @F), @F
  ' file
Tue Aug 21 21:47:30 UTC 2018 some text
Tue Aug 21 21:47:31 UTC 2018 some more text
Tue Aug 21 21:47:32 UTC 2018 text

尽管 GNU 实现sed确实有一个e允许执行外部命令的修饰符,但它在整个模式空间上运行 - 使得在实践中使用起来相当麻烦。

答案3

使用awk:

{
  "date -d @" $1 | getline $1
}
1

结果:

Tue, Aug 21, 2018  4:47:30 PM some text
Tue, Aug 21, 2018  4:47:31 PM some more text
Tue, Aug 21, 2018  4:47:32 PM text

答案4

您需要意识到的是,GNU sed用 的 RHS 中命令求值的结果替换整个模式空间s///e。因此,为了适应这种行为,我们使用echo + date命令组合,如下所示:

 sed -e  's/^\([1-9][0-9]*\)\(.*\)/echo "`date -d@\"\1\"`\2"/e'  input-file.txt

对于Perl,很简单,LHS 上匹配的内容仅在 RHS 上被替换,正如人们直观地期望的那样:

  perl -pe 's/(\d+)/qx(date -d@"$1") =~ s|\n||r/e'  input-file.txt 

相关内容