2010-05-21 84 views
11

在Python中,你可以做這樣的事情Emacs中文本的語言批處理?

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

(我認爲這將是在許多其他類似的語言也一樣)。 在的Emacs Lisp,你會怎麼做,從Emacs Lisp: Process a File line-by-line

(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) 

,我得到了啓發(和代碼)。還是應該嘗試一些完全不同的東西?以及如何從打印語句中刪除""

回答

30

如果你真的想要的stdin批處理和將結果發送到stdout,您可以使用--script命令行選項來Emacs,它將使你編寫代碼,從stdin讀取並寫入stdoutstderr

下面是一個例子程序,它是像cat,除了它反轉每一行:

#!/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)) 

現在,如果你有一個名爲stuff.txt含有

abcd 
1234 
xyz 

一個文件,你調用上面寫的shell腳本(假設它被命名爲rcat):

rcat < stuff.txt 

你會看到下面的打印到stdout:

dcba 
4321 
zyx 

所以,流行的看法相反,你實際上可以做批處理文件的處理上stdin而實際上並沒有讀取整個文件中一次。

+0

...神奇... – hatmatrix 2010-05-26 05:09:52

+4

交叉引用下面的答案,它顯示瞭如何將額外的命令行參數傳遞給Emacs腳本:http://stackoverflow.com/questions/6238331/emacs-shell-scripts-how-對放,初始選擇 - 到 - 在腳本#6259330 – phils 2012-01-03 23:54:08

5

這是我想出來的。看起來更多地給我:

(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不適合處理文件流。整個文件必須一次讀取:

(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'默認情況下在split-string-default-separators中分割,默認爲''[\ f \ t \ n \ r \ v] +「'。你可能想明確地通過'「[\ n \ r] +」'作爲第二個參數。 – haxney 2010-05-21 11:51:38

+1

從技術上講,「Emacs Lisp不適合處理文件流」不正確;你可以使用一個進程過濾器,但它更加複雜,並且一次讀取整個文件可能是最簡單的方法。如果確實需要讀取流(如網絡套接字),則可能必須使用進程過濾器(請參閱Elisp手冊)。 – haxney 2010-05-21 12:00:20

+0

感謝:固定拆分字符串的使用。 – 2010-05-21 12:05:58