代码之家  ›  专栏  ›  技术社区  ›  Anil_M

删除bash inline中由进程主动写入的文件开头的前N个字节/行[duplicate]

  •  -2
  • Anil_M  · 技术社区  · 6 年前

    在连续记录数据时,我需要从日志文件中删除/截断前N个字节。 e、 g.诺胡普。出来

    而我可以用 bash 像这样截断命令。

    truncate -c -s -10K my_file .

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

    我需要从文件的开头(包含较旧的数据)截断文件,并保留新的数据。

    我在网上查过,大多数例子都是使用重定向或写入临时文件 dd , head 等等。我需要在同一个文件中内联执行此操作。

    最接近的匹配是 sed ,但到目前为止,我找到了截短每行N个字符的示例。 e、 g.下面将从我的_文件中的每行删除10个字节。

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

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

    我可能可以编造一些逻辑来实现这一点,但我想知道是否有“现成的”选项可用。

    有什么建议吗? 谢谢

    2 回复  |  直到 6 年前
        1
  •  3
  •   ghoti    6 年前

    以下将打印行,直到包含第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 ,在看到足够的字符后,如果信号量的计算结果为真,则打印。

    这一版本的性能比bash版本低得多,可能如下所示:

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

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

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

    其中x是 人物 您希望从文件的开头进行修剪。如果这不一样,我相信图书馆可能是必要的。

    它的工作原理是搜索时简单地倒计时,并用零替换整行。然后停止进一步处理。这会重写整个文件,可能会有一些实用程序以更聪明的方式完成这项工作。

    要使其可配置,请使用 -s 然后 -- -x=100 (哪个设定 $x via bash):

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