1

前段时间@Oleg Pavliv 在https://unix.stackexchange.com/questions/47615/emacs-simple-arithmetics-in-query-replace中解释了如何在 emacs 中的查询替换(交互式)中进行简单的算术运算。

现在我想对一个小的 elisp 程序使用相同的方法,但它不起作用。例如,考虑以下 elisp 代码的最小示例:

(defun Nshift ()
(interactive)
(query-replace-regexp "\\([0-9]+\\)\\.Number" "\\,((+ 3 \\#1)).Number")
)

现在假设我Nshift在包含例如字符串的缓冲区中运行,4.Number然后我收到以下错误消息。

match-substitute-replacement: Invalid use of `\' in replacement text

一个正确的 elisp 实现Nshift会是什么样子?

编辑:

我看不到 Seans 的答案如何用简单易读的语法概括为更复杂的替换(我在我的应用程序中需要),例如,什么是正确的(并且易于阅读)相当于

(query-replace-regexp "\\([0-9]+\\)\\.Number.\\([0-9]+\\)" "\\,((+ 3 \\#1)).Number.\\,((+ 8 \\#2))")
4

1 回答 1

2

像这样:

(defun Nshift ()
  (interactive)
  (while (search-forward-regexp "\\([0-9]+\\)\\.Number" nil t)
    (replace-match (format "%s.Number" (+ 3 (string-to-number (match-string 1)))))))

编辑添加:

您的扩展示例可以通过这种方式实现:

(defun Nshift ()
  (interactive)
  (while (search-forward-regexp "\\([0-9]+\\)\\.Number\\.\\([0-9]+\\)" nil t)
    (replace-match
     (number-to-string (+ 3 (string-to-number (match-string 1))))
     nil nil nil 1)
    (replace-match
     (number-to-string (+ 8 (string-to-number (match-string 2))))
     nil nil nil 2)))

它实际上比我原来的解决方案更容易,因为我忘记了它replace-match有一个可选的第五个参数,它导致它只替换一个子表达式,并且使您不必在替换文本中复制固定文本(“.Number.”)。

这里可以进行一些重构:

(defun increment-match-string (match-index increment)
  (replace-match
   (number-to-string (+ increment (string-to-number (match-string match-index))))
   nil nil nil match-index))

然后 Nshift 可以这样实现:

(defun Nshift ()
  (interactive)
  (while (search-forward-regexp "\\([0-9]+\\)\\.Number\\.\\([0-9]+\\)" nil t)
    (increment-match-string 1 3)
    (increment-match-string 2 8)))
于 2012-12-13T19:40:12.557 回答