2013-04-13 11 views
5

Her satırda bir cümle içeren bir metin dosyası var. Her satırdaki dünyaları hunspell (-s seçeneği) kullanarak lemmatize etmek isterim. Her satırın ayrı ayrı olmasını istediğimden, tüm metin dosyasını hunspell'e göndermek mantıklı olmaz. Ardından bir satır göndermem ve her satır için hunspell çıkışına ihtiyacım var.SBCL/Common Lisp'de bir işlem giriş/çıkışı ile nasıl etkileşim kurabilirim?

How to process input and output streams in Steel Bank Common Lisp? yanıtlarını takiben, hunspell için bir satır daha ekledim ama her satır için hunspell çıktısını elde edemedim. Başka bir satır göndermeden önce hattı gönderen ve çıktıyı okuyan süreçle nasıl etkileşimde bulunulur? Bütün metin dosyasını okumak için

Benim şu anki kod

(defun parse-spell-sb (file-in) 
    (with-open-file (in file-in) 
    (let ((p (sb-ext:run-program "/opt/local/bin/hunspell" (list "-i" "UTF-8" "-s" "-d" "pt_BR") 
       :input in :output :stream :wait nil))) 
     (when p 
     (unwind-protect 
      (with-open-stream (o (process-output p)) 
      (loop 
     :for line := (read-line o nil nil) 
     :while line 
     :collect line)) 
      (process-close p)))))) 
kez

fazlasıdır, bu kod bana bütün metin dosyası için Hunspell çıktısını verir. Her giriş hattı için ayrı ayrı hunspell çıkışını almak istiyorum.

Herhangi bir fikrin var mı?

+0

@wvxvw sure! Ama hunspell isteminde etkileşimli olarak kullanılabilir. Eğer "hunspell -s" ile başlarım. Bu yüzden CL ile etkileşimli çalışmayı başarabileceğimi düşündüm. En iyi yolun http://common-lisp.net/project/cffi/ olması gerektiği konusunda eminim, ancak hala onunla nasıl çalışacağımı öğrenmek zorundayım. –

cevap

6

Çalıştırmak istediğiniz programla ilgili bir sorun yaşamanız var. Örneğin:

(defun program-stream (program &optional args) 
    (let ((process (sb-ext:run-program program args 
            :input :stream 
            :output :stream 
            :wait nil 
            :search t))) 
    (when process 
     (make-two-way-stream (sb-ext:process-output process) 
          (sb-ext:process-input process))))) 

Şimdi benim sistemde, bu cat ile çalışacaktır:

CL-USER> (defparameter *stream* (program-stream "cat")) 
*STREAM* 
CL-USER> (format *stream* "foo bar baz~%") 
NIL 
CL-USER> (finish-output *stream*)  ; will hang without this 
NIL 
CL-USER> (read-line *stream*) 
"foo bar baz" 
NIL 
CL-USER> (close *stream*) 
T 

Bildirim finish-output - Bu olmadan, salt askıda. (Ayrıca force-output var.) Etkileşimli modda

Python da çalışır:

CL-USER> (defparameter *stream* (program-stream "python" '("-i"))) 
*STREAM* 
CL-USER> (loop while (read-char-no-hang *stream*)) ; skip startup message 
NIL 
CL-USER> (format *stream* "1+2~%") 
NIL 
CL-USER> (finish-output *stream*) 
NIL 
CL-USER> (read-line *stream*) 
"3" 
NIL 
CL-USER> (close *stream*) 
T 

Ama -i seçeneği (veya -u gibi benzer seçenekleri) olmadan bu deneyin, muhtemelen dışarı olacağım şans, tamponlama nedeniyle devam ediyor. Örneğin, benim sistemde, tr okuma askıda kalacaktır: tamponu kapatır için bir anahtar sağlamaz

CL-USER> (defparameter *stream* (program-stream "tr" '("a-z" "A-Z"))) 
*STREAM* 
CL-USER> (format *stream* "foo bar baz~%") 
NIL 
CL-USER> (finish-output *stream*) 
NIL 
CL-USER> (read-line *stream*)   ; hangs 
; Evaluation aborted on NIL. 
CL-USER> (read-char-no-hang *stream*) 
NIL 
CL-USER> (close *stream*) 
T 

tr beri beklediğimiz bu durumda unbuffer bir Pty sarmalayıcı ile görüşmesi (saracağım):

CL-USER> (defparameter *stream* (program-stream "unbuffer" 
               '("-p" "tr" "a-z" "A-Z"))) 
*STREAM* 
CL-USER> (format *stream* "foo bar baz~%") 
NIL 
CL-USER> (finish-output *stream*) 
NIL 
CL-USER> (read-line *stream*) 
"FOO BAR BAZ 
" 
NIL 
CL-USER> (close *stream*) 
T 

Yani, uzun lafın kısası: okumadan önce akışında finish-output kullanmayı deneyin. Bu işe yaramazsa, arabelleğe almayı engelleyen komut satırı seçeneklerini kontrol edin. Eğer hala çalışmıyorsa, programı bir çeşit pty-wrapper ile paketlemeyi deneyebilirsiniz.

+0

Cevabımı yeniden okudum, belki de 'bitirme çıktısının' girişinizin aslında arabelleğe alınmasına rağmen gönderildiğinden emin olmak için kullanıldığını açıklığa kavuşturmalıyım - programın çıktısı ile hiçbir ilgisi yoktur. Ayrıca, iki yönlü akışları kapatırken süreçler kapanmaz (ancak bu, gösterim amaçlı bir sorun değildir). – danlei

+0

@Alexandre: Sorununuzu çözmediniz mi? – danlei

+0

Teşekkürler, danlei. Cevabınız benim için çok değerli. – xiepan

İlgili konular