35.7 Поиск и замена

Если вы хотите найти все совпадения с регулярным выражением в части буфера и заменить их, наиболее гибкий способ — написать явный цикл с использованием re-search-forward и replace-match, например так:

(while (re-search-forward "foo[ \t]+bar" nil t)
  (replace-match "foobar"))

См. Замена текста, совпавшего с шаблоном для описания replace-match.

Бывает удобнее ограничить замены конкретной областью. Функция replace-regexp-in-region делает это.

Функция: replace-regexp-in-region regexp замена &optional начало конец

Эта функция заменяет все вхождения regexp на замена в области текста буфера между начало и конец; начало по умолчанию равно позиции точки, а конец по умолчанию равен последней доступной позиции буфера. Поиск regexp чувствителен к регистру, а замена вставляется без изменения регистра букв. Строка замена может использовать те же специальные элементы, начинающиеся с ‘\’, что и replace-match. Функция возвращает количество заменённых вхождений или nil, если regexp не найден. Функция сохраняет положение точки.

(replace-regexp-in-region "foo[ \t]+bar" "foobar")
Функция: replace-string-in-region строка замена &optional начало конец

Эта функция работает аналогично replace-regexp-in-region, но ищет и заменяет литеральные строки, а не регулярные выражения.

В Emacs также есть специальные функции для замены совпадений в строке.

Функция: replace-regexp-in-string regexp rep строка &optional fixedcase literal subexp начало

Эта функция копирует строку и ищет в ней совпадения с regexp, заменяя их на rep. Она возвращает изменённую копию. Если начало не равно nil, поиск совпадений начинается с этого индекса в строке, а возвращаемое значение не включает первые начало символов строки. Чтобы получить всю преобразованную строку, объедините первые начало символов строки с возвращаемым значением.

Эта функция использует replace-match для выполнения замены и передаёт необязательные аргументы fixedcase, literal и subexp в replace-match.

Вместо строки rep может быть функцией. В этом случае replace-regexp-in-string вызывает rep для каждого совпадения, передавая текст совпадения в качестве единственного аргумента. Она собирает значение, возвращаемое rep, и передаёт его в replace-match как строку замены. Данные о совпадении на этом этапе являются результатом сопоставления regexp с подстрокой строки.

Функция: string-replace из-строки в-строку вх-строка

Эта функция заменяет все вхождения из-строки на в-строку в вх-строке и возвращает результат. Она может вернуть один из своих аргументов без изменений, константную строку или новую строку. Регистр важен, свойства текста игнорируются.

Если вы хотите написать команду наподобие query-replace, вы можете использовать perform-replace для выполнения работы.

Функция: perform-replace из-строка замены query-flag regexp-flag delimited-flag &optional repeat-count map начало конец backward region-noncontiguous-p

Эта функция является ядром query-replace и связанных команд. Она ищет вхождения из-строки в тексте между позициями начало и конец и заменяет некоторые или все из них. Если начало равно nil (или опущено), используется точка, а для конец используется конец доступной части буфера. (Если необязательный аргумент backward не равен nil, поиск начинается с конец и идёт в обратном направлении.)

Если query-flag равен nil, она заменяет все вхождения; в противном случае она спрашивает пользователя, что делать с каждым.

Если regexp-flag не равен nil, то из-строка считается регулярным выражением; в противном случае она должна совпадать буквально. Если delimited-flag не равен nil, то рассматриваются только замены, окружённые границами слов.

Аргумент замены определяет, на что заменять вхождения. Если это строка, используется эта строка. Это также может быть список строк, используемых циклически.

Если замены являются точечной парой (функция . данные), это означает, что нужно вызывать функцию после каждого совпадения для получения текста замены. Эта функция вызывается с двумя аргументами: данные и количество уже выполненных замен.

Если repeat-count не равен nil, это должно быть целое число. Тогда он указывает, сколько раз использовать каждую из строк в списке замены перед циклическим переходом к следующей.

Если из-строка содержит буквы в верхнем регистре, то perform-replace привязывает case-fold-search к nil и использует замены без изменения их регистра.

Обычно клавиатурная карта query-replace-map определяет возможные ответы пользователя на запросы. Аргумент map, если не равен nil, задаёт клавиатурную карту для использования вместо query-replace-map.

Не равный nil region-noncontiguous-p означает, что область между начало и конец состоит из несмежных частей. Наиболее распространённый пример — прямоугольная область, где части разделены символами новой строки.

Эта функция использует одну из двух функций для поиска следующего вхождения из-строки. Эти функции задаются значениями двух переменных: replace-re-search-function и replace-search-function. Первая вызывается, когда аргумент regexp-flag не равен nil, вторая — когда он равен nil.

Переменная: query-replace-map

Эта переменная содержит специальную клавиатурную карту, определяющую допустимые ответы пользователя для perform-replace и команд, которые её используют, а также для y-or-n-p и map-y-or-n-p. Эта карта необычна в двух отношениях:

  • Привязки клавиш — это не команды, а просто символы, имеющие смысл для функций, использующих эту карту.
  • Префиксные клавиши не поддерживаются; каждая привязка клавиш должна быть последовательностью клавиш из одного события. Это потому, что функции не используют read-key-sequence для ввода; вместо этого они читают одно событие и ищут его “вручную”.

Вот значимые привязки для query-replace-map. Некоторые из них имеют смысл только для query-replace и его родственников.

act

Выполнить рассматриваемое действие — другими словами, “да”.

skip

Не выполнять действие для этого вопроса — другими словами, “нет”.

exit

Ответить на этот вопрос “нет” и отказаться от всей серии вопросов, предполагая, что ответы будут “нет”.

exit-prefix

Как exit, но добавить нажатую клавишу в unread-command-events (см. Разные возможности ввода событий).

act-and-exit

Ответить на этот вопрос “да” и отказаться от всей серии вопросов, предполагая, что последующие ответы будут “нет”.

act-and-show

Ответить на этот вопрос “да”, но показать результаты — пока не переходить к следующему вопросу.

automatic

Ответить на этот вопрос и все последующие вопросы в серии “да” без дальнейшего взаимодействия с пользователем.

backup

Вернуться к предыдущему месту, где задавался вопрос.

undo

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

undo-all

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

edit

Войти в рекурсивное редактирование для решения этого вопроса — вместо любого другого действия, которое обычно предпринималось бы.

edit-replacement

Отредактировать замену для этого вопроса в минибуфере.

delete-and-edit

Удалить рассматриваемый текст, затем войти в рекурсивное редактирование, чтобы заменить его.

recenter
scroll-up
scroll-down
scroll-other-window
scroll-other-window-down

Выполнить указанную операцию прокрутки окна, затем задать тот же вопрос снова. Только y-or-n-p и связанные функции используют этот ответ.

quit

Немедленно выполнить выход. Только y-or-n-p и связанные функции используют этот ответ.

help

Показать справку, затем спросить снова.

Переменная: multi-query-replace-map

Эта переменная содержит клавиатурную карту, расширяющую query-replace-map дополнительными привязками клавиш, полезными при заменах в нескольких буферах. Дополнительные привязки:

automatic-all

Ответить на этот вопрос и все последующие вопросы в серии “да” без дальнейшего взаимодействия с пользователем для всех оставшихся буферов.

exit-current

Ответить на этот вопрос “нет” и отказаться от всей серии вопросов для текущего буфера. Перейти к следующему буферу в последовательности.

Переменная: replace-search-function

Эта переменная задаёт функцию, которую perform-replace вызывает для поиска следующей строки для замены. Её значение по умолчанию — search-forward. Любое другое значение должно быть именем функции с 3 аргументами: первые 3 аргумента search-forward (см. Поиск строк).

Переменная: replace-re-search-function

Эта переменная задаёт функцию, которую perform-replace вызывает для поиска следующего регулярного выражения для замены. Её значение по умолчанию — re-search-forward. Любое другое значение должно быть именем функции с 3 аргументами: первые 3 аргумента re-search-forward (см. Поиск по регулярному выражению).