是否可以将程序输出重定向到文件,但有最大行数限制,例如 4 行限制:
./program | save 4 out.txt
将./program
继续每隔几秒提供输出(可能一行或多行),但只有 4 个最近/最后一行将保存到out.txt
.是否已经有一个save
程序可以做到这一点? (或者我应该手动制作)
答案1
对于 shell 的read
内置函数来说,这可能是一项很好的工作 - 只要您的输入是文本,即不包含任何\0NUL
s。我这样说是因为,尽管与其他标准实用程序相比,文件工作效率通常非常低,但使用内置 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