180

我最终在 Python 中为此编写了一个快速的小脚本,但我想知道是否有一个实用程序可以输入文本,它会在每一行前面加上一些文本——在我的具体情况下,是时间戳。理想情况下,使用将类似于:

cat somefile.txt | prepend-timestamp

(在你回答 sed 之前,我试过这个:

cat somefile.txt | sed "s/^/`date`/"

但这仅在执行 sed 时评估 date 命令一次,因此相同的时间戳被错误地附加到每一行。)

4

17 回答 17

203

tsfrom moreutils将为您提供的每一行输入添加一个时间戳。您也可以使用 strftime 对其进行格式化。

$ echo 'foo bar baz' | ts
Mar 21 18:07:28 foo bar baz
$ echo 'blah blah blah' | ts '%F %T'
2012-03-21 18:07:30 blah blah blah
$ 

要安装它:

sudo apt-get install moreutils
于 2012-03-21T22:09:03.750 回答
192

可以尝试使用awk

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }'

您可能需要确保<command>产生行缓冲输出,即在每行之后刷新其输出流;添加的时间戳awk将是行尾出现在其输入管道上的时间。

如果 awk 显示错误,请尝试gawk改用。

于 2008-08-22T01:53:25.837 回答
46

annotate,可通过该链接或annotate-output在 Debiandevscripts软件包中获得。

$ echo -e "a\nb\nc" > lines
$ annotate-output cat lines
17:00:47 I: Started cat lines
17:00:47 O: a
17:00:47 O: b
17:00:47 O: c
17:00:47 I: Finished with exitcode 0
于 2008-08-22T07:00:51.607 回答
31

将给定的答案提炼成最简单的答案:

unbuffer $COMMAND | ts

在 Ubuntu 上,它们来自 expect-dev 和 moreutils 包。

sudo apt-get install expect-dev moreutils
于 2013-10-29T15:17:05.280 回答
25

这个怎么样?

cat somefile.txt | perl -pne 'print scalar(localtime()), " ";'

从您希望获得实时时间戳来看,也许您想对日志文件或其他东西进行实时更新?也许

tail -f /path/to/log | perl -pne 'print scalar(localtime()), " ";' > /path/to/log-with-timestamps
于 2008-08-22T01:42:33.790 回答
19

Kieron 的答案是迄今为止最好的答案。如果您因为第一个程序正在缓冲而遇到问题,您可以使用 unbuffer 程序:

unbuffer <command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

它默认安装在大多数 linux 系统上。如果您需要自己构建它,它是期望包的一部分

http://expect.nist.gov

于 2008-08-22T06:56:48.323 回答
19

只是要把它扔在那里:daemontools中有一对名为tai64ntai64nlocal的实用程序,用于在记录消息之前添加时间戳。

例子:

cat file | tai64n | tai64nlocal
于 2012-03-08T05:58:55.137 回答
10

使用 read(1) 命令从标准输入中一次读取一行,然后使用 date(1) 以您选择的格式输出前面带有日期的行。

$ cat timestamp
#!/bin/sh
while read line
do
  echo `date` $line
done
$ cat somefile.txt | ./timestamp
于 2008-08-22T14:09:11.500 回答
3

我不是 Unix 人,但我认为你可以使用

gawk '{print strftime("%d/%m/%y",systime()) $0 }' < somefile.txt
于 2008-08-22T01:48:58.750 回答
3
#! /bin/sh
unbuffer "$@" | perl -e '
use Time::HiRes (gettimeofday);
while(<>) {
        ($s,$ms) = gettimeofday();
        print $s . "." . $ms . " " . $_;
}'
于 2009-01-12T18:48:23.740 回答
3
$ cat somefile.txt | sed "s/^/`date`/"

你可以这样做(使用gnu/sed):

$ some-command | sed "x;s/.*/date +%T/e;G;s/\n/ /g"

例子:

$ { echo 'line1'; sleep 2; echo 'line2'; } | sed "x;s/.*/date +%T/e;G;s/\n/ /g"
20:24:22 line1
20:24:24 line2

当然,您可以使用程序日期的其他选项。只需替换date +%T为您需要的即可。

于 2017-06-27T17:31:13.243 回答
2

这是我的 awk 解决方案(来自安装在 C:\bin 目录中的 MKS 工具的 Windows/XP 系统)。它旨在以 mm/dd hh:mm 的形式将当前日期和时间添加到每行的开头,并在读取每一行时从系统中获取该时间戳。当然,您可以使用 BEGIN 模式获取一次时间戳并将该时间戳添加到每条记录(都一样)。我这样做是为了用生成日志消息时的时间戳标记正在生成到标准输出的日志文件。

/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | getline timestamp;
print timestamp, $0;

其中“pattern”是要在输入行中匹配的字符串或正则表达式(不带引号),如果您希望匹配所有输入行,则它是可选的。

这也应该适用于 Linux/UNIX 系统,只需去掉 C\:\\bin\\ 即可

             "date '+%m/%d %R'" | getline timestamp;

当然,这假设命令“date”可以让您使用标准 Linux/UNIX 日期显示/设置命令,而无需特定路径信息(即,您的环境 PATH 变量已正确配置)。

于 2011-03-01T18:20:12.483 回答
2

混合了上面来自natevw和 Frank Ch 的一些答案。艾格勒。

date它有毫秒,每次都比调用外部命令执行得更好,并且在大多数服务器中都可以找到 perl。

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday);
  use POSIX qw(strftime);
  ($s,$ms) = gettimeofday();
  print strftime "%Y-%m-%dT%H:%M:%S+$ms ", gmtime($s);
  '

带有刷新和循环读取的替代版本:

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday); use POSIX qw(strftime);
  $|=1;
  while(<>) {
    ($s,$ms) = gettimeofday();
    print strftime "%Y-%m-%dT%H:%M:%S+$ms $_", gmtime($s);
  }'
于 2015-10-19T15:44:06.457 回答
1

caerwyn 的答案可以作为子程序运行,这将阻止每行的新进程:

timestamp(){
   while read line
      do
         echo `date` $line
      done
}

echo testing 123 |timestamp
于 2013-09-20T18:58:45.477 回答
1

免责声明:我提出的解决方案不是 Unix 内置实用程序。

几天前我遇到了类似的问题。我不喜欢上述解决方案的语法和限制,所以我很快在 Go 中编写了一个程序来为我完成这项工作。

您可以在此处查看该工具:preftime

GitHub 项目的“发布”部分中有适用于 Linux、MacOS 和 Windows 的预构建可执行文件。

该工具处理不完整的输出行,并且(从我的角度来看)具有更紧凑的语法。

<command> | preftime

这并不理想,但我想分享它以防它帮助某人。

于 2017-06-25T13:08:47.830 回答
0

在 OSX 上使用dateandtr进行操作:xargs

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S\" | tr \"\n\" \" \"; echo \"{}\"'"
<command> | predate

如果你想要毫秒:

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"

但请注意,在 OSX 上, date 并没有给你 %N 选项,所以你需要安装 gdate ( brew install coreutils) ,所以最后得到这个:

alias predate="xargs -I{} sh -c 'gdate +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"
于 2014-11-18T18:09:52.650 回答
-1

如果您在每一行添加的值都相同,请使用该文件启动 emacs,然后:

Ctrl+<space>

在文件的开头(标记该位置),然后向下滚动到最后一行的开头(Alt + > 将转到文件的末尾......这可能也会涉及 Shift 键,然后是 Ctrl + a 转到该行的开头)和:

Ctrl+x r t

这是在您刚刚指定的矩形(宽度为 0 的矩形)处插入的命令。

2008-8-21 下午 6:45 <进入>

或者任何您想要添加的内容......然后您会看到该文本添加到 0 宽度矩形内的每一行。

更新:我刚刚意识到你不想要相同的日期,所以这不起作用......虽然你可以在 emacs 中使用稍微复杂的自定义宏来做到这一点,但是,这种矩形编辑仍然是很高兴知道...

于 2008-08-22T01:46:58.007 回答