【发布时间】:2014-07-26 00:26:04
【问题描述】:
我正在尝试编写一些 elisp 来处理当前缓冲区中的每个字符 (我知道这会有点慢,但认为这是最好的方法)。我不想使用正则表达式。如何做到这一点?
函数buffer-string 以字符串形式返回当前缓冲区。使用它可以迭代并引用/设置每个字符。但是,我不知道如何将结果放回缓冲区。
有人可以举个例子,只遍历每个字符,用一些简单的方式改变它,然后把结果放回缓冲区吗?
【问题讨论】:
我正在尝试编写一些 elisp 来处理当前缓冲区中的每个字符 (我知道这会有点慢,但认为这是最好的方法)。我不想使用正则表达式。如何做到这一点?
函数buffer-string 以字符串形式返回当前缓冲区。使用它可以迭代并引用/设置每个字符。但是,我不知道如何将结果放回缓冲区。
有人可以举个例子,只遍历每个字符,用一些简单的方式改变它,然后把结果放回缓冲区吗?
【问题讨论】:
使用while 循环和forward-char 遍历缓冲区中的所有字符:
(goto-char (point-min))
(while (not (eobp))
(let* ((current-character (char-after))
(new-character (do-something current-character)))
(delete-char 1)
(insert-char new-character))
(forward-char 1))
只要未到达缓冲区的末尾 (eobp),循环就会一次向前移动一个字符。
char-after 为您提供当前位置的角色。 delete-char/insert-char 调用将旧字符替换为新字符,这是处理旧字符的结果。
要用多个字符(即字符串)替换旧字符,只需将insert-char 替换为insert。 insert 将点 放在 新插入的字符之后,因此循环将继续处理之后的下一个 未处理 字符。
【讨论】:
save-excursion,但其他方法可能更有意义,具体取决于您的场景细节。
save-excursion 来插入多个字符。您只需insert,它隐式地将点放在新插入的字符串之后,因此循环将在之后继续处理下一个原始字符。我相应地更新了答案。
buffer-string,处理该字符串,然后替换使用结果字符串缓冲内容。您想在缓冲区中处理文本。在 Emacs 中,缓冲区的使用效率很高,通常使用它们比使用字符串更好。
为@lunaryorn 所说的内容添加一些内容 - 可能是解决方案的一部分,具体取决于您的需要,而不仅仅是评论:
当您逐个字符处理缓冲区时,很常见的情况是您不希望或不需要为 每个 字符做某事,而是需要为其中的特定字符做某事缓冲区。
在这种情况下,您通常不需要检查每个字符。相反,您可以使用这些函数(请参阅他们的文档了解它们的作用):
search-forward 或 re-search-forward,如果针对特定字符
next-single-property-change,如果目标是一个或多个具有特定文本属性的字符(或者可能是next-single-char-property-change,如果涉及覆盖)
next-property-change,如果针对一个或多个字符,则任何文本属性更改都是目标(或者可能是next-char-property-change,如果涉及覆盖)
在这种情况下,您会遍历缓冲区位置(因此,遍历这些位置的字符),就像@lunaryorn 的解决方案一样,但是您使用这样的函数来快速跳过您不感兴趣的字符。这是 比逐个检查每个字符更常见,IMO。但它是否适合您的用例,我不知道。
【讨论】: