Emacs: добавление 1 к каждому номеру из 2 цифр внутри отмеченной области - PullRequest
25 голосов
/ 22 апреля 2010

Представьте, что в текстовом файле, открытом в Emacs, есть следующее:

some    34
word    30
another 38
thing   59
to      39
say     10
here    47

и я хочу перейти к этому, добавляя 1 к каждому числу, состоящему из 2 цифр:

some    35
word    31
another 39
thing   60
to      40
say     11
here    48

(это короткий пример, моя реальная потребность в гораздо большем списке, а не в моем звонке)

Как я могу сделать это из Emacs?

Я не против вызвать какой-нибудь внешний Perl / sed / любой другой магический режим, если вызов сделан непосредственно из Emacs и работает только в отмеченной области, которую я хочу.

Как бы вы автоматизировали это в Emacs?

Я думаю, что ответ, о котором я думаю, заключается в вызове shell-command-on-region и замене региона на результат ... Но я не уверен, как конкретно сделать это.

Ответы [ 5 ]

44 голосов
/ 22 апреля 2010

Это можно решить с помощью команды query-replace-regexp (привязано к C-M -% ):

C-M -% \b[0-9][0-9]\b Возвращение \,(1+ \#&)

Выражение, следующее за \,, будет оцениваться как выражение Lisp, результат которого используется в качестве строки замены. В выражении Lisp \#& будет заменено на совпавшую строку, интерпретированную как число.

По умолчанию это работает для всего документа, начиная с курсора. Чтобы иметь эту работу в регионе, есть несколько возможностей:

  1. Если transient-mark-mode включен, вам просто нужно выбрать регион нормально (используя точку и метку);
  2. Если по какой-то причине вам не нравится transient-mark-mode , вы можете использовать узко-к региону , чтобы ограничить изменения конкретным регионом: выберите регион используя точку и метку, Cx nn для сужения, выполните query-replace-regexp , как описано выше, и, наконец, Cx nw для расширения. (Спасибо Джастину Смиту за эту подсказку.)
  3. Используйте мышь для выбора региона.

Подробнее см. В разделе Замена Regexp Руководства Emacs.

12 голосов
/ 22 апреля 2010

Emacs ' режим редактирования столбцов - это то, что вам нужно.

  • Активируйте его, набрав M-x cua-mode .

  • Перейти к началу прямоугольника (навести курсор на символ 3) и нажать C-RET .

  • Перейти к концу прямоугольника (оставить курсор на символе 7). Вы будете работать в выделенном регионе.

  • Теперь нажмите M-i , который увеличивает все значения в регионе.

Готово! удаление мертвых ссылок ImageShack

6 голосов
/ 22 апреля 2010

Не защищает от 99-> 100.

(defun add-1-to-2-digits (b e)
  "add 1 to every 2 digit number in the region"
  (interactive "r")
  (goto-char b)
  (while (re-search-forward "\\b[0-9][0-9]\\b" e t)
    (replace-match (number-to-string (+ 1 (string-to-int (match-string 0)))))))

О, и это работает в регионе. Если вам нужен весь файл, то вы замените b и e на (point-min) и nil.

1 голос
/ 22 апреля 2010

умеренно протестировано; используйте M-: и введите следующую команду:

(while (re-search-forward "\\<[0-9][0-9]\\>" nil t) (let ((x (match-string 0))) (delete-backward-char 2) (insert (format "%d" (1+ (string-to-int x))))))
0 голосов
/ 22 апреля 2010

Мне удалось заставить его работать по-другому, используя следующее (мой awk -fu не силен, так что, вероятно, это можно сделать проще):

C-u M-x shell-command-on-region RET awk '$2>=0&&$2<=99 {$2++} {print}' RET

но я потерял свой отступ в процессе:)

Видя все эти ответы, я не могу не уважать Emacs ...

...