【发布时间】:2022-01-18 08:57:26
【问题描述】:
给定文件 (file.org) 如下:
* h1 t1
* h1 t2
* h1 t3
如何读取文件并获得这样的列表?
("h1 t1" "h1 t2" "h1 t3")
【问题讨论】:
-
比什么好?在旁观者的眼中,“更好”也是如此。你应该问:“有没有办法……?” - 如果有多个答案,您可以选择您喜欢的一个。
给定文件 (file.org) 如下:
* h1 t1
* h1 t2
* h1 t3
如何读取文件并获得这样的列表?
("h1 t1" "h1 t2" "h1 t3")
【问题讨论】:
您可以使用映射函数来遍历文件,将函数应用于每个标题。有两种不同的方法。
一种方法使用“Propery API”中的映射函数org-map-entries 和函数org-entry-get。您可以通过 C-h f org-map-entries 和 C-h f org-entry-get 或从手册中找到有关这些的文档:请参阅“黑客”部分以及 Using the Property API 和 Using the Mapping API 小节。
代码如下:
(defun my/headline ()
(org-entry-get nil "ITEM"))
(org-map-entries #'my/headline t 'file)
ITEM 是一个Special Property,其值为标题的文本。
另一种方法是解析缓冲区,得到解析树,然后对解析树进行操作。解析函数是org-element-parse-buffer,遍历解析树的映射函数是org-element-map。这些函数没有在手册中记录,但它们的文档字符串可以通过通常的C-h f 机制获得;还有开发者文档here。思路与第一种方法类似,但细节不同:我们从映射函数传递的解析对象中获取标题文本,所以这个标题函数接受一个参数,标题的解析对象。映射函数本身遍历解析树,将函数应用于每个标题:
(defun my-parsed/headline (o)
(plist-get (cadr o) :raw-value))
(org-element-map (org-element-parse-buffer) 'headline #'my-parsed/headline)
这种方法稍微复杂一些,但更通用,解析树一次后,可以缓存解析树并重复操作:如果摊销成本,这将比第一种方法更快在许多不同的操作中生成解析树。但是对于像这里这样的一次性使用,第一种方法更简单,可能更快一点:解析器相对较慢。
【讨论】: