6

STDINから数行読みました。md5sumSTDIN の残りを、標準入力から読み取るコマンド (または など)に渡すにはどうすればよいwcですか?

私はできる:

read_a_few_lines_from_diamond_operator();
open (C, "|cmd");
while(<>) { print C }
close C;
cleanup_after_C();

しかし、効率的な理由から、入力には触れず、代わりに STDIN のファイルハンドルを渡したいと思います。のような並べ替え:

seq 10 | (read A; wc)

wherereadは好きなだけ読み取り、残りを に渡しwcます。ただし、perl プログラム内からコマンドを開始する必要があり、cmd完了後に作業を行う必要があるため、このソリューションは使用できません。


ファイル「foo」から数行を読み取りました。md5sum残りを標準入力から読み取るコマンド (または など)に渡すにはどうすればよいwcですか?

私はできる:

open (F, "<foo");
read_a_few_lines_from_F();
open (C, "|cmd");
while(<F>) { print C }
close C;
cleanup_after_C();

しかし、効率的な理由から、入力には触れずに、残りのファイル「foo」を渡したいと思います。


、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 、 selectopen(FOO,">&STDOUT)exec 6<&0forkpipe

4

1 に答える 1

8

答えは簡単です。特別なことをする必要はありません。あなたの子供はあなたのSTDINwithsystemとを自動的に継承しますexec。STDIN から読み取っていないものはすべて、子供が読み取ることができます。

ただし、問題があります。一度に 1 文字ずつ読み取るのは非常に効率が悪いため、Perl はファイルから一度に 1 ブロックずつ読み取ります。つまり、Perl から返された「数行」よりも多くをファイルから読み取ったということです。これは、次のコマンドを使用して明確に確認できます。

perl -E'say $_ x 500 for "a".."z"' \
   | perl -e'<>; <>; exec("cat");' \
   | less

2 行目の先頭ではなくcat、"q" の途中 (バイト 8192) から開始します。

これを機能させたい場合は、 readline( <>) を使用した行の読み取りから個々のバイトの読み取りに切り替える必要があります。sysread


全体像に注目すると、解決策があると思います。

open(STDIN, "<", "foo") or die $!;
read_a_few_lines(*STDIN);
my $pos = tell(STDIN);
open(STDIN, "<", "foo") or die $!;
sysseek(STDIN, $pos, SEEK_SET);
system(@cmd);
...

または多分:

open(STDIN, "<", "foo") or die $!;
read_a_few_lines(*STDIN);
sysseek(STDIN, tell(STDIN), SEEK_SET);
system(@cmd);
...

未テスト。

于 2012-08-30T23:27:30.153 に答える