なんだこれは

はてなダイアリーから移転しました。

eml ファイルを csv に変換するlisp作りなおしたので公開する。

むしゃくしゃして、 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)

すればいいんじゃないかな。