将程序输出重定向到具有行数限制的文件

将程序输出重定向到具有行数限制的文件

是否可以将程序输出重定向到文件,但有最大行数限制,例如 4 行限制:

./program | save 4 out.txt

./program继续每隔几秒提供输出(可能一行或多行),但只有 4 个最近/最后一行将保存到out.txt.是否已经有一个save程序可以做到这一点? (或者我应该手动制作)

答案1

对于 shell 的read内置函数来说,这可能是一项很好的工作 - 只要您的输入是文本,即不包含任何\0NULs。我这样说是因为,尽管与其他标准实用程序相比,文件工作效率通常非常低,但使用内置 shell 可能比重复分叉另一个进程更好。无论如何,你不会获得太多效率,因为做到这一点的唯一方法(据我所知)是重复open()输出文件 - 除非您可以非常确定每行的字节数dd(我猜,管道中的一些链接可以保证这一点)。无论如何,以下方法都会起作用:

###seq used for demo###
seq 3 |( set --
while IFS= read -r l
do    set -- "$@" "$l"
      shift "$(($#>4))"
      printf %s\\n "$@" >/tmp/4_lines
###demo commands###
      printf '\n###4_lines CONTENTS###\n'
      cat </tmp/4_lines
      printf '###END###\n'
###end demo###
done)

因此,如果我按照上述方式执行操作,则会将其写入while循环的标准输出:

###4_lines CONTENTS###
1
###END###

###4_lines CONTENTS###
1
2
###END###

###4_lines CONTENTS###
1
2
3
###END###

seq但是,例如,如果我手上有20 个,它就会打印上面的内容:

###4_lines CONTENTS###
1
2
3
4
###END###

###4_lines CONTENTS###
2
3
4
5
###END###

...一直到...

###4_lines CONTENTS###
16
17
18
19
###END###

###4_lines CONTENTS###
17
18
19
20
###END###

它将继续这样直到输入管道关闭 - 只需循环其 arg 数组并在/tmp/4_lines每次输入行时覆盖数组的内容read。如果您希望以相反的顺序排列行 - 因此第一行是读入的最后一行,您可以将该printf行更改为:

printf %s\\n ${4+"$4"} ${3+"$3"} ${2+"$2"} "$1" >/tmp/4_lines

...打印出来就像...

###4_lines CONTENTS###
1
###END###

###4_lines CONTENTS###
2
1
###END###

###4_lines CONTENTS###
3
2
1
###END###

...通过...

###4_lines CONTENTS###
19
18
17
16
###END###

###4_lines CONTENTS###
20
19
18
17
###END###

...不会冒任何$IFS扩展困难和/或无意的问题的风险。

答案2

我认为你可以通过运行来完成你所要求的事情./program | tail -n 4 > out.txt。如果没有,那么我不明白你在问什么。

答案3

save程序可能是这样的:

#include<string>
#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;
int main(int argc,char *argv[]) {
  if(argc<=2) {
    cerr << "First param must be a number, second must be a file" << endl;
    return -1;
  }
  int max = atoi(argv[1]);
  if(max <= 0) return -2;
  string lines[max];
  int cmax = 1;
  int z = 0;
  while(true) {
    getline(cin,lines[z]);
    ++z;
    z %= max;
    ofstream fo(argv[2]);
    for(int x=0;x<cmax;++x) {
      fo << lines[(x+cmax-z)%cmax] << endl;
    }
    fo.close();
    if(cmax<max) ++cmax;
  }
}

编译使用g++ save.cpp -o save

相关内容