是否有一个Unix实用程序来为stdin添加时间戳?

时间:2008-08-22 01:24:35

标签: unix shell awk

我最终在Python中为此编写了一个快速的小脚本,但我想知道是否有一个实用程序可以提供文本,其中每个行前面都有一些文本 - 在我的特定情况下,是一个时间戳。理想情况下,使用方式如下:

cat somefile.txt | prepend-timestamp

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

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

但是这只会在执行sed时评估一次date命令,因此每行都会错误地添加相同的时间戳。)

17 个答案:

答案 0 :(得分:184)

来自moreutils

ts会为您提供的每一行输入添加一个时间戳。您也可以使用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

答案 1 :(得分:183)

可以尝试使用awk

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

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

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

答案 2 :(得分:45)

annotate,可通过该链接或Debian annotate-output包中的devscripts获取。

$ 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

答案 3 :(得分:31)

将给出的答案提炼为最简单的答案:

unbuffer $COMMAND | ts

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

sudo apt-get install expect-dev moreutils

答案 4 :(得分:24)

这个怎么样?

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

从您希望获得实时时间戳来判断,也许您想在日志文件或其他内容上进行实时更新?也许

tail -f /path/to/log | perl -pne 'print scalar(localtime()), " ";' > /path/to/log-with-timestamps

答案 5 :(得分:19)

请将其抛弃:daemontools中有一对名为tai64ntai64nlocal的实用程序,用于预先添加时间戳以记录消息。

示例:

cat file | tai64n | tai64nlocal

答案 6 :(得分:18)

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

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

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

http://expect.nist.gov

答案 7 :(得分:9)

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

$ cat timestamp
#!/bin/sh
while read line
do
  echo `date` $line
done
$ cat somefile.txt | ./timestamp

答案 8 :(得分:3)

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

gawk '{print strftime("%d/%m/%y",systime()) $0 }' < somefile.txt

答案 9 :(得分:3)

#! /bin/sh
unbuffer "$@" | perl -e '
use Time::HiRes (gettimeofday);
while(<>) {
        ($s,$ms) = gettimeofday();
        print $s . "." . $ms . " " . $_;
}'

答案 10 :(得分:2)

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

/"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变量已正确配置)。

答案 11 :(得分:2)

$ 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 的其他选项。只需将date +%T替换为您需要的内容。

答案 12 :(得分:2)

natevw和Frank Ch上面混合上面的一些答案。 Eigler。

它有毫秒,比每次调用外部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);
  '

带有flush和read循环的替代版本:

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);
  }'

答案 13 :(得分:1)

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

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

echo testing 123 |timestamp

答案 14 :(得分:1)

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

几天前我遇到了类似的问题。我不喜欢上面解决方案的语法和限制,所以我很快就把Go中的一个程序放在一起为我做这个工作。

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

GitHub项目的Releases部分中有针对Linux,MacOS和Windows的预构建可执行文件。

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

<command> | preftime

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

答案 15 :(得分:0)

在OSX上使用datetr以及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上,日期并没有为您提供%N选项,因此您需要安装gdate(brew install coreutils),最后到达此处:

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

答案 16 :(得分:-1)

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

Ctrl + &lt; space&gt;

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

Ctrl + x r t

在您指定的矩形(宽度为0的矩形)中插入的命令是什么。

2008-8-21 6:45 PM&lt; enter&gt;

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

更新:我刚刚意识到你不想要相同的日期,所以这不会起作用......虽然你可以在稍微复杂的自定义宏的emacs中做到这一点,但是,这种矩形编辑非常了解...