2010-05-21 14 views
11

अजगर में, आप की तरहEmacs में पाठ की Idiomatic बैच प्रसंस्करण?

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

(मुझे लगता है कि यह रूप में अच्छी तरह कई अन्य भाषाओं में समान होगा) कुछ करना हो सकता है। Emacs लिस्प में, आप से 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 लिए परिणाम भेजते समय, आप Emacs को --script कमांड लाइन विकल्प पर जाकर कोड लिखने के लिए सक्षम हो जाएगा उपयोग कर सकते हैं कि stdin से पढ़ता है और stdout और stderr पर लिखता है।

यहाँ एक उदाहरण प्रोग्राम है जो 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)) 

अब अगर आप जो निहित

abcd 
1234 
xyz 

stuff.txt नाम की एक फ़ाइल था और तुम लागू इस तरह ऊपर लिखी गई शेल स्क्रिप्ट (मान लीजिए कि इसे rcat नाम दिया गया है):

rcat < stuff.txt 

आप stdout में मुद्रित निम्नलिखित देखेंगे:

dcba 
4321 
zyx 

तो, प्रचलित धारणा के विपरीत, आप वास्तव में stdin पर बैच फ़ाइल प्रसंस्करण कर सकते हैं और वास्तव में एक ही बार में में पूरी फ़ाइल को पढ़ने के लिए।

+0

... शानदार ... – hatmatrix

+4

निम्नलिखित उत्तर पर क्रॉस-रेफरेंसिंग जो दिखाती है कि Emacs स्क्रिप्ट्स को अतिरिक्त कमांड-लाइन तर्क कैसे पारित करें: http://stackoverflow.com/questions/6238331/emacs-shell-scripts-how- टू-डाल-प्रारंभिक-विकल्प-में-स्क्रिप्ट # 6259330 – phils

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 लिस्प प्रसंस्करण फ़ाइल-धाराओं के लिए उपयुक्त नहीं है। पूरी फ़ाइल एक ही बार में पढ़ा जाना चाहिए:

(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

'स्प्लिट-स्ट्रिंग' बिना किसी तर्क के 'स्प्लिट-स्ट्रिंग-डिफॉल्ट-सेपरेटर्स' पर विभाजित करने के लिए डिफ़ॉल्ट है, जो डिफ़ॉल्ट रूप से '\ \ f \ t \ n \ r \ v] +" है। आप शायद दूसरे तर्क के रूप में स्पष्ट रूप से '\ [\ n \ r] +" को पास करना चाहते हैं। – haxney

+1

और तकनीकी रूप से, "Emacs Lisp फ़ाइल-स्ट्रीम को संसाधित करने के लिए उपयुक्त नहीं है" सत्य नहीं है; आप एक प्रक्रिया फ़िल्टर का उपयोग कर सकते हैं, लेकिन यह बहुत जटिल है और पूरी फाइल को एक बार में पढ़ना शायद चीजों को करने का सबसे आसान तरीका है। यदि एक स्ट्रीम (जैसे नेटवर्क सॉकेट) पढ़ने की ज़रूरत है, तो आपको शायद एक प्रक्रिया फ़िल्टर का उपयोग करना होगा (एलिसप मैनुअल देखें)। – haxney

+0

धन्यवाद: निश्चित विभाजन-स्ट्रिंग उपयोग। –

संबंधित मुद्दे