むしゃくしゃして、 eml ファイルからcsvにまとめるlisp を作った。勢いにまかせてこの辺に置いた。反省していない。
今はむしゃむしゃしているところである。
適当にディレクトリ移動して、(eml2csv-small)を実行すれば、そのフォルダ以下から拡張子が.txtのものをさがして読み込み、result.csvができているはず。
Clozure CL/ 32bit Windows 7で動作確認をした。
文字コード指定のところだけが Clozure CL なので、すぐに他のものでも動くはず。
(ql:quickload :cl-ppcre) (ql:quickload :csv-parser) ;;;; parameter (defvar *max-message-body-limit* 50) ;; max line for message body ;;;; character coding for read/write-ing file ; if it works on Japanese Windows (setf ccl:*default-external-format* (ccl:make-external-format :character-encoding :cp932 :line-termination :dos)) (defun read-txt-mail (file) (let ((from nil) (subject nil) (date nil) (message-body "") (message-body-count nil)) (with-open-file (in file :direction :input) (loop for line = (read-line in nil nil) while line do (progn (setf from (get-var from line "^From:" "^(From:\\s*)")) (setf subject (get-var subject line "^Subject:" "^(Subject:\\s*)")) (setf date (get-var date line "^Date:" "^(Date:\\s*)")) (if message-body-count (when (< message-body-count *max-message-body-limit*) (incf message-body-count) (setf message-body (format nil "~a~%~a" message-body line))) (when (cl-ppcre:scan "^\\s*$" line) (setf message-body-count 0)))))) (list (namestring file) subject from date message-body))) (defun get-var (var line hit-regex del-regex) (if var var (if (cl-ppcre:scan hit-regex line) (cl-ppcre:regex-replace del-regex line "" ) nil))) (defun eml2csv-small () (with-open-file (out "result.csv" :direction :output :if-exists :supersede) (mapc (lambda (x) (csv-parser:write-csv-line out (read-txt-mail x))) (directory "./*.txt"))))
なぜか cl-fad に嫌われたので、cl-fadに退場していただいた。
それから、1ファイル読む毎に1行(1レコード)書きだすことにしてメモリを節約した。
これを 日本語 Windows で使うには、
(ccl:save-application "eml2csv.exe" :toplevel-function #'eml2csv-small :prepend-kernel t)
すればいいんじゃないかな。