行制限付きファイルへのプログラム出力のリダイレクト

行制限付きファイルへのプログラム出力のリダイレクト

プログラム出力をファイルにリダイレクトできますが、最大行数は4行に制限されます。

./program | save 4 out.txt

は数秒ごとに./program出力(おそらく1つ以上の行)を提供しますが、最新/最後の4行だけに保存​​されます。これを実行できるプログラムはout.txtすでにありますか?save(または手動で作成する必要がありますか?)

答え1

入力がテキストである限り、つまりsが含まれていない限り、これはシェルの組み込みread関数に対してうまく機能します\0NUL。ファイル操作は他の標準ユーティリティと比較して非常に非効率的ですが、組み込みシェルを使用することは他のプロセスを繰り返し分岐するよりも優れているため、これを言うことです。とにかく効率が大幅に得られないでしょう。これを行う唯一の方法は次のとおりです。(私の知る限り)重複した出力ファイルopen()- 1行あたりのバイト数がわからない場合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配列を繰り返し、1行/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

関連情報