实时删除外壳中的回车 [英] Realtime removal of carriage return in shell

查看:72
本文介绍了实时删除外壳中的回车的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于上下文,我试图创建一个shell脚本来简化ffmpeg的实时控制台输出,仅显示当前正在编码的帧.我的最终目标是在某种进度指示器中使用此信息进行批处理.

For context, I'm attempting to create a shell script that simplifies the realtime console output of ffmpeg, only displaying the current frame being encoded. My end goal is to use this information in some sort of progress indicator for batch processing.

对于不熟悉ffmpeg输出的用户,它将已编码的视频信息输出到stdout,将控制台信息输出到stderr.同样,当实际上要显示编码信息时,它使用回车符来防止控制台屏幕被填满.这样就不可能简单地使用grep和awk来捕获适当的行和帧信息.

For those unfamiliar with ffmpeg's output, it outputs encoded video information to stdout and console information to stderr. Also, when it actually gets to displaying encode information, it uses carriage returns to keep the console screen from filling up. This makes it impossible to simply use grep and awk to capture the appropriate line and frame information.

我尝试过的第一件事是使用tr替换回车符:

The first thing I've tried is replacing the carriage returns using tr:

$ ffmpeg -i "ScreeningSchedule-1.mov" -y "test.mp4" 2>&1 | tr '\r' '\n'

此方法的工作原理是将实时输出显示到控制台.但是,如果我随后将该信息通过管道传输到grep或awk或其他任何内容,则tr的输出将被缓冲并且不再是实时的.例如:$ ffmpeg -i "ScreeningSchedule-1.mov" -y "test.mp4" 2>&1 | tr '\r' '\n'>log.txt导致文件立即填充了一些信息,然后5-10秒后,更多行被放入日志文件.

This works in that it displays realtime output to the console. However, if I then pipe that information to grep or awk or anything else, tr's output is buffered and is no longer realtime. For example: $ ffmpeg -i "ScreeningSchedule-1.mov" -y "test.mp4" 2>&1 | tr '\r' '\n'>log.txt results in a file that is immediately filled with some information, then 5-10 secs later, more lines get dropped into the log file.

起初,我认为sed对此非常有用:$ # ffmpeg -i "ScreeningSchedule-1.mov" -y "test.mp4" 2>&1 | sed 's/\\r/\\n/',但它到达所有回车符的行,并等待处理完成,然后再尝试执行任何操作.我认为这是因为sed在逐行的基础上工作,并且需要整行完成后才能执行其他任何操作,然后它无论如何都不会代替回车.我已经为回车和换行尝试了各种不同的正则表达式,但是还没有找到替代回车的解决方案.我正在运行OSX 10.6.8,所以我使用的是BSD sed,这可能是造成这种情况的原因.

At first I thought sed would be great for this: $ # ffmpeg -i "ScreeningSchedule-1.mov" -y "test.mp4" 2>&1 | sed 's/\\r/\\n/', but it gets to the line with all the carriage returns and waits until the processing has finished before it attempts to do anything. I assume this is because sed works on a line-by-line basis and needs the whole line to have completed before it does anything else, and then it doesn't replace the carriage returns anyway. I've tried various different regex's for the carriage return and new line, and have yet to find a solution that replaces the carriage return. I'm running OSX 10.6.8, so I am using BSD sed, which might account for that.

我还试图将信息写入日志文件,并使用tail -f读回,但是我仍然遇到实时替换回车的问题.

I have also attempted to write the information to a log file and use tail -f to read it back, but I still run into the issue of replacing carriage returns in realtime.

我已经看到在python和perl中有针对此的解决方案,但是,我不愿意立即走这条路线.首先,我不了解python或perl.其次,我有一个功能齐全的批处理外壳应用程序,需要移植或弄清楚如何与python/perl集成.除非我绝对必须,否则可能并不难,但不是我想进入的内容.因此,我正在寻找一种外壳解决方案,最好是bash,但是任何OSX外壳都可以.

I have seen that there are solutions for this in python and perl, however, I'm reluctant to go that route immediately. First, I don't know python or perl. Second, I have a completely functional batch processing shell application that I would need to either port or figure out how to integrate with python/perl. Probably not hard, but not what I want to get into unless I absolutely have to. So I'm looking for a shell solution, preferably bash, but any of the OSX shells would be fine.

如果我想要的东西根本无法实现,那么我想我到达那儿后会越过那座桥.

And if what I want is simply not doable, well I guess I'll cross that bridge when I get there.

推荐答案

如果仅是管道之后接收应用程序进行输出缓冲的问题.然后,您可以尝试使用gawk(和某些BSD awk)或mawk可以刷新缓冲区.例如,尝试:

If it is only a matter of output buffering by the receiving application after the pipe. Then you could try using gawk (and some BSD awk) or mawk which can flush buffers. For example, try:

... | gawk '1;{fflush()}' RS='\r\n' > log.txt

或者,如果awk不支持此功能,则可以通过重复关闭输出文件并追加下一行来强制执行此操作...

Alternatively if you awk does not support this you could force this by repeatedly closing the output file and appending the next line...

... | awk '{sub(/\r$/,x); print>>f; close(f)}' f=log.out

或者您也可以只使用shell,例如在bash中:

Or you could just use shell, for example in bash:

... | while IFS= read -r line; do printf "%s\n" "${line%$'\r'}"; done > log.out

这篇关于实时删除外壳中的回车的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆