[求助] elisp关于文件的读取与写入过程碰到的问题

大佬们能否帮看看,我想要实现的简单程序是这样的,把信息从a01.in文件中读出来,简单处理后再写入到a01.out文件中,弄了两个函数:

(defun read-file-as-lines (file-path)
  (with-temp-buffer
    (insert-file-contents file-path)
    (split-string (buffer-string) "\n" t)
    ))

read-file-as-lines 逐行读入文件内容

(defun deal_list (list n rlist)
  (if (< n (length list))
      (progn 
       (setq rlist (cons  (nth n list) rlist))
       (deal_list list (+ 1 n) rlist)
      )
      )
  )

rlist 参数作为结果链表,简单获取每一行处理后的结果,这里直接复制

(let (
      (in_list (read-file-as-lines "a01.in"))
      (result_list nil)
      )
  (with-temp-buffer
    (deal_list in_list 0 result_list)
    (write-region result_list nil "a01.out")
    )
  )

结果发现写入到文件a01.out时,是空的,不知是哪里出了问题?

从标题看不出你在分享还是求助。

一、你deal_list写错了,result_list并没有被modify,所以一直是nil

二、write-region也用错了,write-region长这个样:

(write-region START END FILENAME &optional APPEND VISIT LOCKNAME MUSTBENEW)

是将buffer从start到end这个region里的东西写进file(所以叫write-region)。

由于你的result_list其实是nil(write-region nil nil "a01.out")会把当前buffer的所有内容写进a01.out。因为是temp buffer所以结果是个空文件。


对于deal_list,一个简单的做法是不要尝试修改外面的result_list,而是直接返回rlist。然后你就可以这样写:

(let* ((in_list (read-file-as-lines "a01.in"))
       (result_list (deal_list in_list)))
  (with-temp-buffer
    ...))

deal_list大概可以长这个样:

(defun deal_list (list-of-lines)
  (let ((i 0)
        (rlist nil))
    (dolist (line list-of-lines)
      ;; 对line做某些操作
      ...
      ;; 放进rlist
      (push ... rlist)
      (setq i (1+ i)))
    (nreverse rlist)))

这个还可以有很多种写法,取决于你想做什么。

然后就是把result_list写进buffer,这同样取决于你result_list里有什么,如果都是字符串的话可以简单地(insert (string-join result_list "\n"))

最后(write-region nil nil "a01.out")

2 个赞

感谢大佬指导,我再试试 :grinning:

感谢大佬,已经成功解决了,不过感觉deal_list里不需要局部变量 i,我把它改成这样也好使:

(defun deal_list (list-of-lines)
  (let (
	;; (i 0)
	(rlist nil)
	)
    (dolist (line list-of-lines rlist)
      (push line rlist)
      ;; (setq i (1+ i))
      ;; (nreverse rlist)
	)
    (nreverse rlist)
    )
  )

你写 deal_list 目的是什么?

如果你是想练习一下函数的写法,除了 #3 楼给的迭代写法,递归可以这样写:

(defun deal_list (list)
  (when list
    (let ((line (car list)))
      (cons (... line) ;; 对 line 做某些操作
            (deal_list (cdr list))))))

如果你的重点在于结果,用 mapcar 更简单:

(mapcar (lambda (line)
          ;; 对 line 做某些操作, 并返回
          )
        list)

或者:

(defun deal_line (line)
  ;; 对 line 做某些操作, 并返回
  )

(mapcar #'deal_line list)