почему множественные вызовы re-search-foward / replace-match не заменяют все совпадения? - PullRequest
1 голос
/ 21 июля 2011

Я хочу выполнить набор операций поиска и замены в emacs, поэтому я написал эту функцию:

defun untwist ()
 (interactive)
 (while (re-search-forward "yield " nil t) (replace-match ""))
 (while (re-search-forward "@defer.inlineCallbacks" nil t) (replace-match ""))
 (while (re-search-forward "defer.returnValue" nil t) (replace-match "return "))
 (while (re-search-forward "@inlineCallbacks" nil t) (replace-match ""))
 (while (re-search-forward "returnValue" nil t) (replace-match "return "))
 (while (re-search-forward "^from twisted\.+\n" nil t) (replace-match ""))
 (while (re-search-forward "(session," nil t) (replace-match "("))
 (while (re-search-forward "session\.log(\(.*\))" nil t) (replace-match "print \1"))
)

Однако, только некоторые замены выполняются.Я запустил его:

@defer.inlineCallbacks
yield x

и получил:

@defer.inlineCallbacks
x

Что я делаю не так?

Ответы [ 3 ]

3 голосов
/ 21 июля 2011

Ваша проблема в том, что после того, как первый оператор while успешно заменяет оператор yield, «точка» помещается в конец буфера. Поэтому все последующие поиски RE не находят ничего для замены, потому что их поиски начинаются в конце буфера! Вы можете легко исправить это, переместив курсор в начало буфера после каждого поиска:

(defun untwist ()
 (interactive)
 (while (re-search-forward "yield " nil t) (replace-match ""))
 (beginning-of-buffer)
 (while (re-search-forward "@defer.inlineCallbacks" nil t) (replace-match ""))
 (beginning-of-buffer)
 (while (re-search-forward "defer.returnValue" nil t) (replace-match "return "))
 (beginning-of-buffer)
 (while (re-search-forward "@inlineCallbacks" nil t) (replace-match ""))
 (beginning-of-buffer)
 (while (re-search-forward "returnValue" nil t) (replace-match "return "))
 (beginning-of-buffer)
 (while (re-search-forward "^from twisted\.+\n" nil t) (replace-match ""))
 (beginning-of-buffer)
 (while (re-search-forward "(session," nil t) (replace-match "("))
 (beginning-of-buffer)
 (while (re-search-forward "session\.log(\(.*\))" nil t) (replace-match "print \1"))
)
1 голос
/ 21 июля 2011

Как было отмечено, курсор (или «точка») не возвращается в начальную точку после каждой операции замены.Небольшая вспомогательная функция может упростить задачу:

(defun replace-regexp-and-return (from to)
  (save-excursion
    (while (re-search-forward from nil t)
      (replace-match to))))

Затем вы можете написать свою untwist функцию как:

(defun untwist ()
  (interactive)
  (replace-regexp-and-return "yield " "")
  (replace-regexp-and-return "@defer.inlineCallbacks" "")
  (replace-regexp-and-return "defer.returnValue" "return ")
  (replace-regexp-and-return "@inlineCallbacks" "")
  (replace-regexp-and-return "returnValue" "return ")
  (replace-regexp-and-return "^from twisted\.+\n" "")
  (replace-regexp-and-return "(session," "(")
  (replace-regexp-and-return "session\.log(\(.*\)" "print \1"))

Однако вы, вероятно, захотите сказать "^from twisted\\.+\n" вместо"^from twisted\.+\n", "session\\.log(\\(.*\\)" вместо "session\.log(\(.*\)" и "print \\1" вместо "print \1".(Чтобы получить обратную косую черту через механизм регулярных выражений Emacs, вам нужно экранировать их в строке. Так же, как в Java.)

0 голосов
/ 21 июля 2011

Вам нужно вернуться к началу файла (или где-либо еще) между вашими циклами. Попробуйте использовать (goto-char (point-min)) или что-то подобное

...