在defun

时间:2015-08-11 02:29:53

标签: regex search replace emacs

从Emacs的第22版开始,我们可以使用\,(function)来操作(部分)正则表达式搜索结果,然后再替换它。但是 - 这经常被提及,但仍然是事实 - 我们只能以标准的交互方式使用这种结构。 (互动式:按C-M-%或使用query-replace-regexp致电M-x。)

举个例子:

如果我们有

  • [Foo Bar 1900]

想要

  • [Foo Bar \ function {foo1900} {1900}]

我们可以使用:

M-x query-replace-regexp <return>
  \[\([A-Za-z-]+\)\([^0-9]*\) \([0-9]\{4\}\)\]    
  [\1\2 \\function{\,(downcase \1)\3}{\3}] 

完成它。所以这可以很容易地完成。

在我自己的defun中,只能通过替换而不自由修改匹配来使用查询,修改准备好的替换字符串而不进行任何查询。我看到的唯一方法是以这种方式序列化它:

(defun form-to-function () 
  (interactive)
  (goto-char (point-min))
  (while (query-replace-regexp 
    "\\[\\([A-Za-z-]+\\)\\([^0-9]*\\) \\([0-9]\\{4\\}\\)\\]" 
    "[\\1\\2 \\\\function{\\1\\3}{\\3}]" ))
  (goto-char (point-min))
  (while (search-forward-regexp "\\([a-z0-9]\\)" nil t) 
    (replace-match (downcase (match-string 1)) t nil)
 )
)

对我而言查询很重要,因为我无法确定缓冲区为我提供了什么(=我无法确定,作者使用了这种字符串总是以同样的方式)。

我想使用elisp函数,因为它不是唯一的重复替换(并且不仅是一个缓冲区(我知道dired-do-query-replace-regexp但我更喜欢使用replace-defuns缓冲区工作))

起初我以为我只会遗漏query-replace-match而不是replace-match。但我担心,我也错过了重新排列query-replace-regexp字符串的简单灵活方式。

所以我想,我需要一个\,用于defun。我真的很想知道,如果我是唯一一个错过这个功能的人。

2 个答案:

答案 0 :(得分:2)

如果你想让你的rsearch&amp; replace提示用户,这意味着你希望它是交互式的,所以调用query-replace-regexp是完全可以的(即使字节编译器会告诉你这是为了仅限交互式使用)。如果警告困扰您,您可以将电话打包在with-no-warnings或致电perform-replace

perform-replace的文档字符串遗憾地没有(或者说“直到今天”没有“说明replacements参数的格式是什么,但你可以在函数的代码中看到它:

;; REPLACEMENTS is either a string, a list of strings, or a cons cell
;; containing a function and its first argument.  The function is
;; called to generate each replacement like this:
;;   (funcall (car replacements) (cdr replacements) replace-count)
;; It must return a string.

答案 1 :(得分:1)

query-replace-function不仅可以将替换作为字符串处理,还可以作为包含操作元素的列表处理。使用concat档案构建各种元素的字符串。

因此,在插入替换之前想要通过函数操纵搜索匹配的人也可以在defun中使用query-replace-regexp

(defun form-to-function () 
  (interactive)
  (goto-char (point-min))
  (query-replace-regexp 
   "\\[\\([A-Za-z-]+\\)\\([^0-9]*\\) \\([0-9]\\{4\\}\\)\\]"
   (quote (replace-eval-replacement concat "[\\1\\2 \\\\function{" 
    (replace-quote (downcase (match-string 1))) "\\3}{\\3}]")) nil ))
  • match-string 1返回regexp-search的第一个表达式。

  • `replace-quote'帮助我们双击以下表达式。

  • concat从以下元素中形成一个字符串。

  • replace-eval-replacement未记录在案。

为什么它在这里使用,是因为emacs似乎在内部使用它,同时执行第一个»交互«query-replace-regexp调用。至少是通过向repeat-complex-command询问emacs来给出的。

我在repeat-complex-command的源代码中搜索答案时遇到query-replace-regexp(绑定到[C-x M-:]。)。

因此,通过执行标准搜索和替换方法可以很容易地创建defunved,如第一次成功按[Cx M-:]导致已经生成Lisp的命令,可以复制和粘贴在defun。

编辑(perform-replace

正如Stefan所说,可以使用perform-replace来避免使用query-replace-regexp

这样的功能可能是:

(defun form-to-function () 
  (interactive)
  (goto-char (point-min))
  (while (perform-replace
      "\\[\\([A-Za-z-]+\\)\\([^0-9]*\\) \\([0-9]\\{4\\}\\)\\]"
      (quote (replace-eval-replacement concat "[\\1\\2 \\\\function{"
      (replace-quote (downcase (match-string 1))) "\\3}{\\3}]"))
       t t nil)))

第一个布尔值(t)是查询标志,第二个是正则表达式开关。所以它也很完美,但它没有帮助找到替换表达式,就像使用\,一样简单。