多行转换为单行并输出到文件

时间:2013-09-17 18:19:15

标签: linux

我有一个写多行事件的日志文件。事件以________________开头,包含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

我该如何解决这个问题?

2 个答案:

答案 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}//