从进程开始主动写入的bash内联文件中删除文件开头的前N个字节/行

时间:2018-08-29 20:04:25

标签: bash sed

我需要在连续记录数据的同时从日志文件中删除/截断前N个字节。 例如nohup.out

虽然我可以像这样使用bash截断命令。

truncate -c -s -10K my_file

这将截断文件末尾的最新数据。因此在这种情况下没有用。

我需要从文件的开头(包含较旧的数据)开始将其截断并保存新的文件。

我在线检查过,大部分示例都使用重定向或使用ddhead等写入临时文件。我需要在同一文件上内联执行此操作。

最接近的匹配是sed,但是到目前为止,我发现了从每行中截断N个字符的示例。 例如下面将从my_file的每一行中删除10个字节。

sed -i 's/^\(.\)\{10\}//g' my_file

我正在寻找可以删除从第1行开始到第K行的前N个字节的选项,其中第N个要删除的字节结束,从而将最新数据保留在底部。

我可能可以通过一些逻辑来实现此目的,但是想知道是否有“现成的”选项可用。

有指针吗? 谢谢。

2 个答案:

答案 0 :(得分:1)

perl -i -pe 'BEGIN{$x=100} {if ($x > 0) {$x -= length$_; s/^.*\r?\n?//;}}' file

其中x是要从文件开头修剪的字符的数量。如果不一样,我认为可能需要一个库。

它的工作原理是在搜索时简单地递减计数,并将整行替换为空。然后,它将停止进一步处理。这将重写整个文件,并且可能会有实用程序以更巧妙的方式执行此操作。

要使其可配置,请使用-s,然后使用---x=100(通过bash设置$x):

perl -i -spe 'if ($x > 0) {$x -= length$_; s/^.*\r?\n?//;}' -- -x=100 file

答案 1 :(得分:1)

以下将打印行,直到包含第N个字节的行为止:

awk -v n="$n" 'c>=n{exit} {c+=length()+1} 1'

其中shell变量$n包含对您来说很重要的字节数。 +1在那里,所以将包括换行符。如果您没有单字符换行符,请调整为适合,或者改用length(ORS)

请注意,这不会处理您请求中不可能完成的部分,即在另一个进程打开文件进行写入时更改文件。

要实现这一目的,即打印从第N个字节开始的每一行,我们需要做些不同的事情:

awk -v n="$n" 'c>=n{p=1} {c+=length()+1} p'

这将设置一个信号量p,一旦看到足够的字符,然后在该信号量评估为true时进行打印。

性能相当低的等效bash版本可能看起来像:

c=0; p=0
while read; do
  ((c>=n)) && p=1
  ((c+=${#REPLY}+1))
  ((p)) && echo "$REPLY"
done

您可以将其用作管道,也可以使用输入重定向来读取文件。它还假定$n包含一个整数。