2

我的目标是删除 xml 文件中重复的节。如果在文件中多次找到该节的第一行,我确信我有一个重复的节。

我创建了一个宏,它通过交互式搜索找到我的节的第一行,然后再次按 Ctrl-S 转到下一个匹配项。如果找到,然后我标记我要删除的部分并将其删除。我的宏在这里终止。

如果我的 Ctrl-s 没有找到下一个匹配项,我的宏就会停止,这正是我想要它做的。但是,当我 Esc 1000 Ctrl-x e 多次执行我的宏时,当发现错误时,1000 循环也会停止。我很高兴宏停止,但我想在出错后再次执行它。这可能吗?或者是否已经有一个宏可以从文件中删除重复的节或行组?

我的宏:

C-s         ;; isearch-forward
<Conduit        ;; self-insert-command * 8
SPC         ;; self-insert-command
6*C-w           ;; kill-region
C-s         ;; isearch-forward
C-a         ;; beginning-of-line
C-SPC           ;; set-mark-command
C-s         ;; isearch-forward
<           ;; self-insert-command
/           ;; nxml-electric-slash
Conduit>        ;; self-insert-command * 8
<right>         ;; forward-char
C-w         ;; kill-region

谢谢

4

3 回答 3

1

If what you want to achieve is to run a macro repeatedly regardless of errors, this would be a way to do it:

(defun repeat-macro-until-abort ()
  (interactive)
  (while t
    (ignore-errors
      (kmacro-call-macro 0))))

It will run your last macro until you hit C-g. Please notice that it won't be stopped even by reaching end-of-buffer.

于 2013-11-11T07:55:17.110 回答
1

唔。如果 Emacs 提供了一种方便的交互方式来处理键盘宏中的错误情况,那就太好了,但我怀疑 juanleon 的答案可能是你目前最好的选择。

一般的解决方法是不使用C-s,而是使用类似M-: (search-forward "foo" nil t) RET搜索“foo”的东西,如果它不存在则不会触发错误。不过,在这个例子中会有更多内容。

对于一次性处理,在这种情况下,我倾向于生成我感兴趣的结果的缓冲区,然后使用键盘宏进行处理。

这个例子实际上有点棘手,但是您可以将occur所有匹配模式的行,通过管道sort | uniq --all-repeated=separate,然后消除每个组的第一行。这样一来,您就可以为每个重复项删除确切数量的实例,因此您的键盘宏可以从该列表中抓取一行,在原始缓冲区中找到它的最后一个实例,将其删除,然后移至下一行在列表中。

如果这是一个常见的活动,自定义 elisp 函数似乎是可行的方法。

于 2013-11-11T11:50:28.847 回答
0

有一种简单的方法可以删除与正则表达式匹配的行:M-x flush-lines

如果您知道要删除的节的正则表达式,则可以键入C-M-% <your-regexp> RET RET并遍历选择要删除的内容的出现(键入!删除每个)。CM-% 是query-replace-regexp.

于 2013-11-06T09:41:55.927 回答