次のPerlスクリプトはconsume-10-lines-and-exit
stdinから10行を読み込み、印刷します。その後は終了します。
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
for (my $i = 0; $i < 10; $i++) {
my $line = <STDIN>;
print $line;
}
入力合計の最初の10行が消費され、最初のコマンドによって印刷され、残りが消費されるようにconsume-10-lines-and-exit
合計を結合しようとしています。cat
cat
以下のコードスニペットは、期待どおりに1〜13の代わりに1〜10をすべて印刷します。
printf '1 2 3 4 5 6 7 8 9 10 11 12 13' \
| tr ' ' '\n' | { perl consume-10-lines-and-exit; cat; }
printf '1 2 3 4 5 6 7 8 9 10 11 12 13' \
| tr ' ' '\n' | ( perl consume-10-lines-and-exit; cat )
printf '1 2 3 4 5 6 7 8 9 10 11 12 13' \
| tr ' ' '\n' | sh -c 'perl consume-10-lines-and-exit; cat'
コマンドが終了するまでstdinから入力を読み込み、次のコマンドが前のコマンドがハングしたところで続くようにコマンドをソートする構造はありますか?
答え1
問題は、Perlがバッファリングされた入力を使用するので、使用したいよりも多くの行を事前に読み取るということです。次のバイト単位のバージョンを試してください。
perl -e '
use strict;
use warnings FATAL => "all";
for (my $i = 0; $i < 10; $i++) {
my $line;
while(sysread(*STDIN,my $char,1)==1){
$line .= $char;
last if $char eq "\n";
}
print $line;
}'
答え2
グループコマンドを使用することはその操作には適していますが、グループコマンドに入力した入力が検索されないことが原因です。
POSIXで定義INPUT FILE
部分:
標準ユーティリティが検索可能な入力ファイルを読み取り、ファイルの終わりに到達する前にエラーなしで終了する場合、ユーティリティは、開かれたファイル記述のファイルオフセットがユーティリティが処理した最後のバイトの後に正しく配置されていることを確認する必要があります。検索できないファイルの場合、ファイルのオープンファイル記述にファイルオフセット状態は指定されません。
perl
標準ユーティリティではありませんが、標準仕様に従う可能性が高いです。ファイルを検索可能に設定すると、次のように動作します。
$ seq 13 > /tmp/test
$ {perl -e 'for($i=0;$i<10;$i++){$line = <STDIN>;print $line}'; cat;} </tmp/test
1
2
3
4
5
6
7
8
9
10
11
12
13
検索可能ファイルを使用したくない場合は、IOの下位レベルのシステムコール関数をperl
使用するように強制できます。read()
write()
lseek()
$ seq 13 | {
PERLIO=:unix perl -e 'for($i=0;$i<10;$i++){$line = <STDIN>;print $line}'
cat
}
答え3
バッファリングは、次の操作で無効にすることもできます。PerlIOレイヤー(また参照フェレン)。さらに、厄介で長いCスタイルのループは、... for 1..10
またはで簡単に作成できますfor my $i (1..10) { ... }
。
$ perl -E 'say for 1..12' \
| ( PERLIO=:unix perl -e 'print "perl " . scalar <STDIN> for 1..10'; cat )
perl 1
perl 2
perl 3
perl 4
perl 5
perl 6
perl 7
perl 8
perl 9
perl 10
11
12
$