0

我希望有人可以帮助我解决问题。我发现了很多关于使用 sed 读取文件的主题,但没有什么适合我的情况。也许有人知道以下情况的解决方案:

我有一个记录器,它创建一个定义大小的文件(在我的例子中是 5MB)。记录器像环形缓冲区一样使用该文件,并将记录器信息写入此文件。记录器当然从第 1 行开始,并用 eof 注释结尾。在十六进制编辑器中,它看起来像这样:

0d 3c 3c 3c 45 4f 46 3e 3e 3e 0d 20 20 20 20 20  .<<<EOF>>>.

现在我有两种情况,一种简单的,一种复杂的:

  1. 我需要从头到尾打印标识符。

  2. 最漂亮的解决方案是识别 EOF 之后是否是初始值(0x20),然后从第 1 行打印到 EOF。如果行尾标识符之后有值,则在 EOF 之后读取所有值,直到文件大小,然后从第一行读取到 EOF 标识符。这应该打印出这个“环形缓冲区”的所有行。这样的事情可能吗?

为了解决(1)我尝试了一些sed命令,例如:

sed -e '1,$p' test.log > result.txt 

-> 目标:打印从第 1 行到 EOF 模式的所有内容,但两个文件的大小相同(在我的情况下为 5MB)。看起来 $p 指的是文件的真实结尾,而不是 EOF 模式。

sed -e '/EOF/,$d' test.log > result.txt 

-> 目标:打印 EOF 模式之前的所有内容,但 result.txt 的大小为 0。

任何人都可以提供任何提示或解决方案来解决这个问题吗?

4

1 回答 1

0

使用sed,我认为您需要两个命令(以及文件的两次扫描):

logfile="…some-name…"
eofmark="<<<EOF>>>"

sed -n "/$eofmark/,\$ { /$eofmark/d; p; }" $logfile  # Read the tail material
sed -n "1,/$eofmark/  { /$eofmark/d; p; }" $logfile  # Read the head material

使用perlor awk,您可以将整个文件放入内存中,然后打印尾部部分,然后打印头部部分。例如,在awk

logfile="…some-name…"
eofmark="<<<EOF>>>"

awk "/$eofmark/"' {eofline = NR}
     {line[NR] = $0}
     END { for (i = eofline+1; i <= NR; i++) print line[i]
           for (i = 1; i < eofline; i++) print line[i]
     }' $logfile

这是可行的,因为将 5 MiB 的文件读入内存不会对拥有千兆字节主内存的机器造成压力。如果文件本身是千兆字节的数据,你会三思而后行将它吞入内存,尽管扫描两次也会很痛苦。

于 2014-12-15T08:17:30.830 回答