2010-05-21 7 views
11

En Python, que podría hacer algo comoProcesamiento idiomático por lotes de texto en Emacs?

fout = open('out','w') 
fin = open('in') 
for line in fin: 
    fout.write(process(line)+"\n") 
fin.close() 
fout.close() 

(creo que sería similar en muchos otros idiomas también). En Emacs Lisp, habría que hacer algo como

(find-file 'out') 
(setq fout (current-buffer) 
(find-file 'in') 
(setq fin (current-buffer) 
(while moreLines 
(setq begin (point)) 
(move-end-of-line 1) 
(setq line (buffer-substring-no-properties begin (point)) 
;; maybe 
(print (process line) fout) 
;; or 
(save-excursion 
    (set-buffer fout) 
    (insert (process line))) 
(setq moreLines (= 0 (forward-line 1)))) 
(kill-buffer fin) 
(kill-buffer fout) 

que me dieron la inspiración (y el código) de Emacs Lisp: Process a File line-by-line. ¿O debería intentar algo completamente diferente? Y cómo eliminar el "" de la declaración de impresión?

Respuesta

30

Si realmente quiere procesamiento por lotes de stdin y enviar el resultado a stdout, puede utilizar la opción de línea --script comando para Emacs, lo que le permitirá escribir código que lee desde stdin y escribe en stdout y stderr.

Aquí es un programa de ejemplo que es como cat, excepto que se invierte cada línea:

#!/usr/local/bin/emacs --script 
;;-*- mode: emacs-lisp;-*- 

(defun process (string) 
    "just reverse the string" 
    (concat (nreverse (string-to-list string)))) 

(condition-case nil 
    (let (line) 
     ;; commented out b/c not relevant for `cat`, but potentially useful 
     ;; (princ "argv is ") 
     ;; (princ argv) 
     ;; (princ "\n") 
     ;; (princ "command-line-args is") 
     ;; (princ command-line-args) 
     ;; (princ "\n") 

     (while (setq line (read-from-minibuffer "")) 
     (princ (process line)) 
     (princ "\n"))) 
    (error nil)) 

Ahora, si usted tenía un archivo llamado stuff.txt que contenía

abcd 
1234 
xyz 

Y se invoca la shell script escrito arriba como tal (suponiendo que se llame rcat):

rcat < stuff.txt 

que verá la siguiente en la salida estándar:

dcba 
4321 
zyx 

Así, contrariamente a la creencia popular, en realidad se puede hacer el proceso archivo por lotes en stdin y en realidad no tiene que leer todo el archivo a la vez.

+0

... Fantástico ... – hatmatrix

+4

Referencia cruzada a la siguiente respuesta que muestra cómo pasar argumentos de línea de comandos adicionales a los scripts de Emacs: http://stackoverflow.com/questions/6238331/emacs-shell-scripts-how- to-put-initial-options-into-the-script # 6259330 – phils

5

Esto es lo que se me ocurrió. Me parece mucho más idiomático:

(with-temp-buffer 
    (let ((dest-buffer (current-buffer))) 
    (with-temp-buffer 
     (insert-file-contents "/path/to/source/file") 
     (while (search-forward-regexp ".*\n\\|.+" nil t) 
     (let ((line (match-string 0))) 
      (with-current-buffer dest-buffer 
      (insert (process line))))))) 
    (write-file "/path/to/dest/file" nil)) 
1

Emacs Lisp no es adecuado para el procesamiento de secuencias de archivos. El archivo de conjunto debe leerse a la vez:

(defun my-line-fun (line) 
    (concat "prefix: " line)) 

(let* ((in-file "in") 
     (out-file "out") 
     (lines (with-temp-buffer 
     (insert-file-contents in-file) 
     (split-string (buffer-string) "\n\r?")))) 
    (with-temp-file out-file 
    (mapconcat 'my-line-fun lines "\n"))) 
+1

'split-string' sin ningún argumento por defecto se divide en' split-string-default-separators', que es '" [\ f \ t \ n \ r \ v] + "' por defecto. Probablemente quiera pasar '" [\ n \ r] + "' explícitamente como el segundo argumento. – haxney

+1

Y técnicamente, "Emacs Lisp no es adecuado para procesar flujos de archivos" no es verdadero; podría usar un filtro de proceso, pero es mucho más complicado y leer todo el archivo de una vez es probablemente la manera más fácil de hacer las cosas. Si realmente se necesita leer un flujo (como un enchufe de red), probablemente tenga que usar un filtro de proceso (consulte el manual de Elisp). – haxney

+0

Gracias: uso fijo de string dividido. –

Cuestiones relacionadas