2017-01-27 10 views
5

awkは、Rebol 3を使って大きなテキストファイルをbashパイプやツールで処理するツールのようにしようとしています。私はRebol 3の行ごとにSTDIN行を読むのに問題がありますか?Rebol 3:STDINを行単位で効率的に読む

例えば、このシェルコマンドは3行生成します

$ (echo "first line" ; echo "second line" ; echo "third line") 
first line 
second line 
third line 

をしかし、REBOLのの入力言葉は、同時にすべての3行を読み取ります。私は入力をインタラクティブに使用すると、改行が止まると停止することを期待しています。

r3 --do 'while [ x: input ] [ if empty? x [ break ] print x print "***" ]' 
abcdef 
abcdef 
*** 
blabla 
blabla 
*** 

しかし、すべて一緒に実行すると、一度に入力全体が読み込まれます。私はそれをすべて一度に読んで行に分けることができましたが、私は通常、ストリーミングの方法で動作するようにしたいと思います。多くの1000-s行。

$ (echo "first line" ; echo "second line" ; echo "third line") \ 
    | r3 --do 'while [ x: input ] [ if empty? x [ break ] print x print "***" ]' 
first linesecond linethird line 
*** 

Iはまた、同様の機能を行うこと入力のソースを見ました。私はで文字ごとに文字を読み取ることができ、ループと改行をチェックすると効率的ではないようです。

答えて

4

私はそれを理解しました。大きな10000行のファイルでもうまくいくようです。それはよりエレガントに書かれ、改善されたかもしれません。

r3awk: func [ code /local a lines line partial ] [ 
    partial: copy "" 
    lines: read/lines/string system/ports/input 
    while [ not empty? lines ] [ 
     lines/1: rejoin [ partial lines/1 ] 
     partial: pull lines 
     foreach line lines [ 
      do bind code 'line 
     ] 
     if error? try [ lines: read/lines/string system/ports/input ] [ lines: copy [] ] 
    ] 
    line: partial 
    do bind code 'line 
]  

それがこのように動作:

機能r3awkSTDIN及びそれにライン変数を結合、行ごとに実行されるコードのブロックを取ります。 read/linesは、ストリームからいくつかの文字を読み取り、行のブロックを返します。呼び出されるたびに、このような文字の次のバッチが読み込まれるので、whileループですべてがラップされます。コードはwhileループ(最後ではありません)として処理します(コードブロックを処理します)。

文字のバッチは改行で終わらないので、最後の行は部分です。次のバッチの最初の行も同様です。したがって、それらは一緒に結合されます。最後に、最後の(今回は非部分的な)行を処理しなければなりません。 を試してください。一部の行でutfのエンコーディングエラーが発生したためです。

コマンドラインで次のように使用することができます:

(echo "first line" ; echo "second line" ; echo "third line") | \ 
r3 --import utils.r --do 'r3awk [ parse line [ copy x to space (print x) ] ]' 
first 
second 
third 

物事を改善するために:一般的に、より良い機能を作り、いくつかのコードを重複排除します。読み込み/改行が改行で完全に終わったらどうなるか確認してください。

+0

良い発見。しかし、それはMacOS(OSX)で私にとってはうまくいきません:(ブロックの代わりに34815バイトの 'バイナリ! 'を返す(STDINが使い果たされるまで)。と '/ string')はMacOSでは何もしません:( – draegtun

3

私は数年前にinputと同じ問題を抱えていました。私はこれが計画された変更だとは思っていませんが、むしろ不完全な実装(タッチウッド!)だと思います。

これは、私がMacOS & Linuxでうまくいきましたその時に書いた回避策です。

input-line: function [ 
    {Return next line (string!) from STDIN. Returns NONE when nothing left} 
    /part size [integer!] "Internal read/part (buffer) size" 
    ][ 
    buffer: {} ;; static 
    if none? part [size: 1024] 

    forever [ 
     if f: find buffer newline [ 
      remove f ;; chomp newline (NB. doesn't cover Windows CRLF?) 
      break 
     ] 

     if empty? data: read/part system/ports/input size [ 
      f: length? buffer 
      break 
     ] 

     append buffer to-string data 
    ] 

    unless all [empty? data empty? buffer] [take/part buffer f] 
] 

使用例:STDIN上の `読み/ lines`バッファリングについて

while [not none? line: input-line] [ 
    ;; do something with LINE of data from STDIN 
] 
関連する問題