EMACS Lisp程序员如何读取文本文件以进行非编辑?

Lio*_*bro 6 emacs file-io elisp

EMACS Lisp程序员做什么,当他们想写一些大致相当于......的东西时...

for line in open("foo.txt", "r", encoding="utf-8").readlines():
    ...(split on ws and call a fn, or whatever)...
Run Code Online (Sandbox Code Playgroud)

..?

当我查看EMACS lisp帮助时,我看到有关将文件打开到文本编辑缓冲区的功能 - 不完全是我想要的.我想我可以编写函数来访问文件的行,但是如果我这样做,我就不希望用户看到它,而且从文本处理的角度看它似乎不是很有效.

Sea*_*ean 9

我认为原始Python代码的更直接的翻译如下:

(with-temp-buffer
  (insert-file-contents "foo.txt")
  (while (search-forward-regexp "\\(.*\\)\n?" nil t)
    ; do something with this line in (match-string 1)
    ))
Run Code Online (Sandbox Code Playgroud)

我认为with-temp-buffer/ insert-file-contents通常比with-current-buffer/ 更好find-file-noselect,因为前者保证你正在使用整个文件内容的新副本.对于后一种结构,如果您碰巧已经有一个访问目标文件的缓冲区,那么该缓冲区将被返回find-file-noselect,因此如果该缓冲区已经缩小,那么在处理它时您将只看到该文件的那一部分.

请记住,逐行处理文件可能更方便.例如,这是一个表达式,它返回文件中所有连续数字序列的列表:

(with-temp-buffer
  (insert-file-contents "foo.txt")
  (loop while (search-forward-regexp "[0-9]+" nil t)
        collect (match-string 0)))
Run Code Online (Sandbox Code Playgroud)

(require 'cl)首先引入loop宏.


Dre*_*rew 5

  1. 是的,这就是您想要做的:访问缓冲区中的文件,并对该缓冲区中的文本进行操作。

  2. 您不必显示缓冲区,即用户不需要看到它。

  3. 至于效率:在缓冲区中操作文本通常是操作文本的最有效方法。


您可以通过多种方式访问​​缓冲区中的文件。您可能希望使用现有的文件缓冲区来实现此目的,具体取决于用例。也就是说,如果文件已经在 Emacs 中“打开”,那么您可能想要使用它的缓冲区。

或者您可能希望忽略已经“打开”的文件的任何现有文件缓冲区,并将该文件重新读入新缓冲区。为此,正如 @Sean 提到的,您可以使用insert-file-contents您创建的缓冲区。with-temp-buffer您可以使用或创建缓冲区generate-new-buffer,这又取决于您想要/需要用它做什么。

如果您确实想重用已经访问该文件的缓冲区,您可以测试它是否已在内存中修改,是否缩小等,并执行适合您的用例的任何操作。您可以使用 function 检查是否已经有一个缓冲区访问该文件(使用任何路径/文件名)find-buffer-visiting

要访问该文件,利用正在访问该文件的任何现有缓冲区,您可以使用find-file-noselect. 该函数返回访问文件的缓冲区,因此您可以将该缓冲区作为第一个参数传递给with-current-buffer. 这是一个简单的例子。

(with-current-buffer (let ((enable-local-variables  ())) (find-file-noselect file))
  ;; Do some stuff with the text in the buffer.
  ;; Optionally save the buffer back to the file.
  )
Run Code Online (Sandbox Code Playgroud)

enable-local-variables( to的绑定nil是一个小的优化,对于通常情况下您不需要担心缓冲区局部变量。)