我有一个写多行事件的日志文件。事件以________________
开头,包含n个详细说明事件的行,并在两个换行符之后结束。
每次将事件写入日志文件时,我想将此多行事件合并为一行,并将其输出到另一个文件,该文件将这些事件包含为单行。
如何在Linux中执行此操作?
根据给定的建议,我想出了下面的代码。
tail -f audit.log | perl -pe 'chomp; s/^(_____)/\n$1/' | tr '\r' '\t' |
tr -d '________________________________________________________________________________' > audit_test1.log &
但是,在我终止后台作业之前,该文件不会写audit.log
生成的任何内容。当我终止该作业时,输出将写入audit_test1.log
。
我该如何解决这个问题?
答案 0 :(得分:2)
Perl单线程应该或多或少地完成工作。 -pe
选项意味着用while (<>) { YOUR_SCRIPT; print }
循环包围命令行中指定的脚本,
它逐行读取输入文件(或stdin),删除(扼杀)换行符,并在以_____
开头的任何行之前添加换行符。
修复一些小问题,例如删除第一个额外的空行,并添加行连接的空格,留作OP的练习。 : - )
perl -pe 'chomp; s/^(_____)/\n$1/' file > another_file
要在后台(&amp;)实时转换日志文件(tail -f):
tail -f file | perl -pe 'chomp; s/^(_____)/\n$1/' > another_file &
答案 1 :(得分:0)
问题是输出缓冲。你必须让Perl运行无缓冲。
http://mywiki.wooledge.org/BashFAQ/009是关于此主题的众多常见问题解答之一。
您需要set $| = 1
to make STDOUT
unbuffered in Perl。但是,如果要运行两个实例,则还必须使tr
无缓冲。由于Perl可以完成tr
可以执行的所有操作,因此无论如何都可以在Perl中执行所有处理。
tail -f audit.log | perl -pe 'BEGIN { $| = 1 } chomp; s/^(_____)/\n$1/;
tr/\r/\t/; tr/_//d' > audit_test1.log &
如果Perl是管道中的最后一个,缓冲问题应该会消失,但为了以防万一我将其留下。
顺便说一下,tr
只能替换你给它的每个字符的所有出现,所以重复______
80个字符可能不会达到预期的效果。如果打算删除那么多字符的运行但保留其他字符,那么最好在Perl中执行s/_{80}//
。