是否有 Unix 实用程序可以将时间戳添加到标准输入?
我最终用 Python 编写了一个快速的小脚本,但我想知道是否有一个实用程序可以将文本输入其中,在每行前面添加一些文本 - 在我的具体情况下,是时间戳。 理想情况下,用法如下:(
cat somefile.txt | prepend-timestamp
在回答 sed 之前,我尝试了以下操作:
cat somefile.txt | sed "s/^/`date`/"
但这仅在执行 sed 时计算一次 date 命令,因此相同的时间戳错误地添加到每行前面。)
I ended up writing a quick little script for this in Python, but I was wondering if there was a utility you could feed text into which would prepend each line with some text -- in my specific case, a timestamp. Ideally, the use would be something like:
cat somefile.txt | prepend-timestamp
(Before you answer sed, I tried this:
cat somefile.txt | sed "s/^/`date`/"
But that only evaluates the date command once when sed is executed, so the same timestamp is incorrectly prepended to each line.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(19)
来自 moreutils 的
ts
将为每行输入添加时间戳你给它。 您也可以使用 strftime 对其进行格式化。要安装它:
ts
from moreutils will prepend a timestamp to every line of input you give it. You can format it using strftime too.To install it:
注释,可通过该链接或作为
annotate-output
在 Debiandevscripts
包中。annotate, available via that link or as
annotate-output
in the Debiandevscripts
package.可以尝试使用 awk:
您可能需要确保
产生行缓冲输出,即它在每行之后刷新其输出流; awk 添加的时间戳将是该行末尾出现在其输入管道上的时间。如果 awk 显示错误,请尝试使用
gawk
。Could try using
awk
:You may need to make sure that
<command>
produces line buffered output, i.e. it flushes its output stream after each line; the timestampawk
adds will be the time that the end of the line appeared on its input pipe.If awk shows errors, then try
gawk
instead.无需在
strftime()
中指定所有参数,除非您确实想要自定义输出格式:如果您有
mawk 1.3.4,则效果相同。
即使在上>awk
-没有时间特征的变体,快速 getline 可以模拟它:如果你想跳过所有 getline 和 BEGIN { },那么像这样:
No need to specify all the parameters in
strftime()
unless you really want to customize the outputting format :works the same if you have
mawk 1.3.4.
Even onawk
-variants without the time features, a quick getline could emulate it :If you wanna skip all that getline and BEGIN { }, then something like this :
如果您在每一行前面添加的值都相同,请使用该文件启动 emacs,然后:
Ctrl +
在文件的开头(标记该位置),然后向下滚动到最后一行的开头(Alt + > 将转到文件末尾...这可能也涉及 Shift 键,然后 Ctrl + a 转到开头该行)和:
Ctrl + x r t
这是要在您刚刚插入的矩形处插入的命令指定(宽度为 0 的矩形)。
2008-8-21 6:45PM <进入>
或者您想要添加的任何内容...然后您将看到该文本添加到 0 宽度矩形内的每一行。
更新:我刚刚意识到你不想要相同的日期,所以这不起作用......虽然你可以在 emacs 中使用稍微复杂的自定义宏来完成此操作,但是,这种矩形编辑仍然是很高兴知道...
If the value you are prepending is the same on every line, fire up emacs with the file, then:
Ctrl + <space>
at the beginning of the of the file (to mark that spot), then scroll down to the beginning of the last line (Alt + > will go to the end of file... which probably will involve the Shift key too, then Ctrl + a to go to the beginning of that line) and:
Ctrl + x r t
Which is the command to insert at the rectangle you just specified (a rectangle of 0 width).
2008-8-21 6:45PM <enter>
Or whatever you want to prepend... then you will see that text prepended to every line within the 0 width rectangle.
UPDATE: I just realized you don't want the SAME date, so this won't work... though you may be able to do this in emacs with a slightly more complicated custom macro, but still, this kind of rectangle editing is pretty nice to know about...
Kieron 的答案是迄今为止最好的答案。 如果由于第一个程序正在缓冲其输出而遇到问题,您可以使用 unbuffer 程序:
它默认安装在大多数 Linux 系统上。 如果您需要自己构建它,它是expect包的一部分
http://expect.nist.gov
Kieron's answer is the best one so far. If you have problems because the first program is buffering its out you can use the unbuffer program:
It's installed by default on most linux systems. If you need to build it yourself it is part of the expect package
http://expect.nist.gov
将给出的答案提炼为最简单的答案:
在 Ubuntu 上,它们来自 Expect-dev 和 moreutils 软件包。
Distilling the given answers to the simplest one possible:
On Ubuntu, they come from the expect-dev and moreutils packages.
这个怎么样?
从您想要获取实时时间戳的愿望来看,也许您想对日志文件或其他内容进行实时更新? 或许
How about this?
Judging from your desire to get live timestamps, maybe you want to do live updating on a log file or something? Maybe
只是想把这个扔出去:daemontools中有一对名为tai64n 和 tai64nlocal 用于前置记录消息的时间戳。
例子:
Just gonna throw this out there: there are a pair of utilities in daemontools called tai64n and tai64nlocal that are made for prepending timestamps to log messages.
Example:
这是我的 awk 解决方案(来自 Windows/XP 系统,MKS Tools 安装在 C:\bin 目录中)。 它旨在以 mm/dd hh:mm 的形式将当前日期和时间添加到每行的开头,并在读取每行时从系统获取时间戳。 当然,您可以使用 BEGIN 模式来获取时间戳一次并将该时间戳添加到每个记录中(都一样)。 我这样做是为了使用生成日志消息时的时间戳来标记正在生成到标准输出的日志文件。
/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | 获取行时间戳;
print timestamp, $0;
其中“pattern”是要在输入行中匹配的字符串或正则表达式(不带引号),如果您希望匹配所有输入行,则该模式是可选的。
这也应该适用于 Linux/UNIX 系统,只需去掉 C\:\\bin\\ 留下该行
当然,假设命令“date”让您进入标准的 Linux/UNIX 日期显示/ set命令没有具体的路径信息(即你的环境PATH变量配置正确)。
Here's my awk solution (from a Windows/XP system with MKS Tools installed in the C:\bin directory). It is designed to add the current date and time in the form mm/dd hh:mm to the beginning of each line having fetched that timestamp from the system as each line is read. You could, of course, use the BEGIN pattern to fetch the timestamp once and add that timestamp to each record (all the same). I did this to tag a log file that was being generated to stdout with the timestamp at the time the log message was generated.
/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | getline timestamp;
print timestamp, $0;
where "pattern" is a string or regex (without the quotes) to be matched in the input line, and is optional if you wish to match all input lines.
This should work on Linux/UNIX systems as well, just get rid of the C\:\\bin\\ leaving the line
This, of course, assumes that the command "date" gets you to the standard Linux/UNIX date display/set command without specific path information (that is, your environment PATH variable is correctly configured).
你可以这样做(使用gnu/sed):
示例:
当然,你可以使用程序的其他选项日期。 只需将
date +%T
替换为您需要的内容即可。you can do this (with gnu/sed):
example:
of course, you can use other options of the program date. just replace
date +%T
with what you need.我不是 Unix 爱好者,但我认为你可以使用
I'm not an Unix guy, but I think you can use
使用 read(1) 命令从标准输入中一次读取一行,然后使用 date(1) 以您选择的格式输出前置有日期的行。
Use the read(1) command to read one line at a time from standard input, then output the line prepended with the date in the format of your choosing using date(1).
其他答案大多有效,但有一些缺点。 特别是:
[timestamp] [timestamp] stdout line \nstderr line
为了解决(4),我们可以使用大多数Linux系统上普遍可用的
stdbuf -i0 -o0 -e0
(参见如何使任何 shell 命令的输出不缓冲?)。要解决(3)问题,您只需小心地一次打印整行即可。
ruby -pe 'print Time.now.strftime(\"[%Y-%m-%d %H:%M:%S] \")'
(打印时间戳,然后打印$_
的内容。)ruby -pe '\$_ = Time.now.strftime(\"[%Y-%m-%d %H:%M :%S] \") + \$_'
(改变$_
,然后打印它。)为了解决(2),我们需要使用多个管道并保存退出状态:
然后您可以使用 tslines some command --options 运行命令。
这几乎有效,只是有时其中一个管道需要稍长的时间才能退出,并且
tslines
函数已退出,因此已打印下一个提示。 例如,此命令似乎在出现下一行提示后打印所有输出,这可能有点令人困惑:两个管道进程和 tslines 函数之间需要某种协调方法。 想必有很多方法可以做到这一点。 我发现的一种方法是让管道向主函数可以侦听的管道发送一些行,并且只有在从两个管道处理程序接收到数据后才退出。 综合起来:
同步机制感觉有点复杂; 希望有一种更简单的方法来做到这一点。
The other answers mostly work, but have some drawbacks. In particular:
[timestamp] [timestamp] stdout line \nstderr line
unbuffer
requires an extra dependency.To solve (4), we can use
stdbuf -i0 -o0 -e0
which is generally available on most linux systems (see How to make output of any shell command unbuffered?).To solve (3), you just need to be careful to print the entire line at a time.
ruby -pe 'print Time.now.strftime(\"[%Y-%m-%d %H:%M:%S] \")'
(Prints the timestamp, then prints the contents of$_
.)ruby -pe '\$_ = Time.now.strftime(\"[%Y-%m-%d %H:%M:%S] \") + \$_'
(Alters$_
, then prints it.)To solve (2), we need to use multiple pipes and save the exit status:
Then you can run a command with
tslines some command --options
.This almost works, except sometimes one of the pipes takes slightly longer to exit and the
tslines
function has exited, so the next prompt has printed. For example, this command seems to print all the output after the prompt for the next line has appeared, which can be a bit confusing:There needs to be some coordination method between the two pipe processes and the tslines function. There are presumably many ways to do this. One way I found is to have the pipes send some lines to a pipe that the main function can listen to, and only exit after it's received data from both pipe handlers. Putting that together:
That synchronization mechanism feels a bit convoluted; hopefully there's a simpler way to do it.
免责声明:我提出的解决方案不是 Unix 内置实用程序。
几天前我遇到了类似的问题。 我不喜欢上述解决方案的语法和限制,所以我很快用 Go 编写了一个程序来帮我完成这项工作。
您可以在此处查看该工具: preftime
有针对 Linux 的预构建可执行文件, MacOS 和 Windows 位于 GitHub 项目的 发布 部分。
该工具可以处理不完整的输出行,并且(从我的角度来看)具有更紧凑的语法。
<代码><命令>; | preftime
这并不理想,但我想我会分享它,以防它对某人有帮助。
Disclaimer: the solution I am proposing is not a Unix built-in utility.
I faced a similar problem a few days ago. I did not like the syntax and limitations of the solutions above, so I quickly put together a program in Go to do the job for me.
You can check the tool here: preftime
There are prebuilt executables for Linux, MacOS, and Windows in the Releases section of the GitHub project.
The tool handles incomplete output lines and has (from my point of view) a more compact syntax.
<command> | preftime
It's not ideal, but I though I'd share it in case it helps someone.
在 OSX 上使用
date
和tr
和xargs
执行此操作:如果您想要毫秒:
但请注意,在 OSX 上,date 不会为您提供%N 选项,所以你需要安装 gdate (
brew install coreutils
),最终得到这个:doing it with
date
andtr
andxargs
on OSX:if you want milliseconds:
but note that on OSX, date doesn't give you the %N option, so you'll need to install gdate (
brew install coreutils
) and so finally arrive at this:混合上面 natevw 和 Frank Ch. 的一些答案。 艾格勒。
它有几毫秒,比每次调用外部
date
命令执行得更好,而且大多数服务器中都可以找到perl。具有刷新和循环读取的替代版本:
Mixing some answers above from natevw and Frank Ch. Eigler.
It has milliseconds, performs better than calling a external
date
command each time and perl can be found in most of the servers.Alternative version with flush and read in a loop:
caerwyn 的答案可以作为子例程运行,这将阻止每行新进程:
caerwyn's answer can be run as a subroutine, which would prevent the new processes per line: