Функція пошуку / заміни для заміни тексту


12

Я часто ловлю себе намагається замінити , наприклад , fooз barі barз fooв буфері.

Я зазвичай це роблю:

  • 3 запити-Замінює: aaa -> @@@, bbb -> aaa,@@@ -> bbb
  • відмовтеся від автоматизації і просто зробіть заміну вручну

Я припускаю, що можна перевірити, чи відповідає збіг рядка або що- небудь працює, використовуючи ,синтаксис . Але отриманий синтаксис був би занадто громіздким, тому я його ніколи не намагався.query-replace-regexpaaabbb

Вся справа в тому, наскільки це загальне завдання, я думаю, що повинен бути кращий, одноетапний спосіб його виконання, або вбудований, або в існуючому пакеті. Є там?


Можливо, є один крок, але ваш перший шлях непоганий, ІМО. І якщо ви обираєте рядок заміни правильно, то ви можете просто зробити заміну без запитів для другого проходу.
Дрю

@Drew Зазвичай query-replaceя знаю, що зазвичай швидше, M-% str1 str2ніж рухати крапку і робити зміни вручну. Це приємно, адже мені не потрібно витрачати час на роздуми про те, що буде найшвидше, навіть якщо є лише один випадок str1. В ідеалі я хотів би, щоб інверсія тексту була настільки ж швидкою, щоб я міг використовувати її, не замислюючись про це.
Т. Веррон

Хтось дасть просту відповідь. Ви можете, без сумніву, робити те, що ви просите, наприклад, використовуючи вираз Lisp для заміни, посилаючись на текст, що підлягає заміні. Наприклад, використовуйте щось подібне до ідіоми swap (setq a (prog1 b (setq b a))). І навіть може бути простіший спосіб.
Дрю

2
Я не вважаю \,(if \1 "b" "a")особливо некрасивим (проти зворотного перегляду \(a\)\|b), але все-таки слова потрібно вводити двічі, якщо це вас турбує.
politza

2
Чому ні \(aaa\)\|bbb?
politza

Відповіді:


8

Ось невелика команда, яка зробить це:

(defun query-swap-strings (from-string to-string &optional delimited start end)
  "Swap occurrences of FROM-STRING and TO-STRING."
  (interactive
   (let ((common
          (query-replace-read-args
           (concat "Query swap"
                   (if current-prefix-arg
                       (if (eq current-prefix-arg '-) " backward" " word")
                     "")
                   (if (use-region-p) " in region" ""))
           nil)))
     (list (nth 0 common) (nth 1 common) (nth 2 common)
           (if (use-region-p) (region-beginning))
           (if (use-region-p) (region-end)))))
  (perform-replace
   (concat "\\(" (regexp-quote from-string) "\\)\\|" (regexp-quote to-string))
   `(replace-eval-replacement replace-quote (if (match-string 1) ,to-string ,from-string))
   t t delimited nil nil start end))

Дякую, це набагато складніше, ніж те, що я написав би сам! Можливо, ви могли б детальніше розробити реалізовані функції? Я бачу, що з аргументом префікса ви переходите назад, що він виконує заміну лише в регіоні, якщо це потрібно ... Або це просто переписування query-replaceінверсії, щоб вона зберігала всі свої особливості? Це не відповідає 100% визначенню в моїх програмах emacs, але я все ще з 24.5 ...
Т. Веррон

@ T.Verron Це лише стандартний корпус із query-replaceсімейства функцій з останньої версії, тому він зберігає всі функції. В кінці функції я додав рекомендований спосіб заміни рядків, згаданий у посібнику Emacs.
link0ff

Я, мабуть, прийняв занадто швидко. Ця функція працює тут лише (emacs 24.3), якщо я коментую backwardі region-noncontiguous-pпід час виклику до perform-replace. Це загальна проблема, чи це означає, що інтерфейс до perform-replaceзмінився між версіями?
Т. Веррон

Так, інтерфейс змінився з цими двома аргументами, доданими в останній версії, тому їх не існує в більш ранній,
link0ff

2
Це рішення також зараз здається нормальним.
Ім'я

9

Встановіть plur

і запустіть команду plur-query-replace

та введення {foo,bar}та його заміна{bar,foo}

Натисніть, yщоб замінити події за бажанням.

Існують також неінтерактивні варіанти пошуку, подібні до пошуку.


Дякую! Призначення plur - це теж те, що я іноді шукав, я обов'язково буду дивитись на це. Моє єдине вагання випливає з коментаря автора пакета вище ...;)
Т. Веррон

1
plurвимагає emacs 24.4.
Т. Веррон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.