2017-01-27 14 views
5

Daha büyük metin dosyalarını bash boruları ve araçlarıyla işlemek için Rebol 3 kullanan bir araç gibi bir awk yapmaya çalışıyorum. Rebol 3'te STDIN hattını okuyarak bir problem yaşıyorum?Rebol 3: STDIN'i verimli bir şekilde satır satırına göre okuma (awk benzeri bir araç yapmak için)

Örneğin bu kabuk komutu 3 satırları üretir:

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

Ama Rebol 'giriş kelime aynı anda tüm 3 satırları okur. Girişimi etkileşimli olarak kullanırsanız, durağan olarak durduğunu beklerim.

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

Ancak hepsini bir arada yürüttüğümde, bir kerede tüm girdileri okur. Hepsini bir kerede okuyabiliyor ve satırlara bölübiliyordum, ancak 1000 satırlık bir satırda genelde kedi gibi "akış" tarzında çalışmasını istiyorum.

$ (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 
*** 

Ben de benzer bir işlevi yapmak için girdi kaynağı baktı. Karakter başına numarasını döngüde okuyabilir ve satır sayısını kontrol edebilirim, ancak bu etkili görünmüyor.

cevap

4

Bunu anladım ve büyük, 10000 satırlık dosyalarda bile iyi çalışıyor gibi görünüyor. Yine de daha zarif ve gelişmiş yazılabilir.

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 
]  

Bu gibi çalışır:

fonksiyonu r3awkSTDIN ve bunun için hat değişken bağlama satıra yürütür kod bloğunu almaktadır. read/lines akıştan bir dizi karakter okur ve bir satır bloğu döndürür. Her çağrıldığında böyle bir karakter kümesini okur, bu yüzden hepsi bir süre döngüsüne sarılır. Kod süreçleri (kod bloğu) zaman döngülerinde (sonunda değil) işler.

Karakterlerin toplu iş akışı yeni satırda bitmez, bu nedenle her seferinde son satır kısmi olur. Ve bir sonraki partinin ilk satırı da bu yüzden onları bir araya getiriyor. Sonunda, son (bu kez kısmi olmayan) çizgiyi işlemek zorundadır. 'u deneyin, çünkü bazı çizgiler utf kodlama hatalarına neden oldu.

komut satırında bu gibi kullanılabilir:

(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 

Artırmak için şeyler: genellikle daha iyi işlev yapmak, bazı kod deduplicate. Okunur/satırlar tam olarak yeni satırda bitiyorsa ne olduğunu kontrol edin.

+0

İyi bulmak 'STDIN/lines' tamponlama okuyun. Ancak MacOS'ta (OSX) benim için tam olarak çalışmıyor :(Bir 'blok! 'Yerine, 34815 bayt (STDIN bitene kadar) bir' binary!' Döndürür.NB aslında '/ lines' (ve '/ string') MacOS'ta bir şey yapmıyor :( – draegtun

3

Birkaç yıl önce input ile aynı problemle karşılaştım. Bunun planlı bir değişiklik olduğunu, bunun yerine tamamlanmamış bir uygulama olduğunu düşünmüyorum (dokunma ahşabı!).

İşte o sırada yazdığım bir geçici çözüm (MacOS & Linux'ta benim için iyi çalıştı).

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] 
] 

Kullanım örneği: yaklaşık

while [not none? line: input-line] [ 
    ;; do something with LINE of data from STDIN 
] 
İlgili konular