Search code examples
emacselisp

Emacs: adding 1 to every number made of 2 digits inside a marked region


Imagine I've got the following in a text file opened under Emacs:

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

and I want to turn into this, adding 1 to every number made of 2 digits:

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

(this is a short example, my actual need is on a much bigger list, not my call)

How can I do this from Emacs?

I don't mind calling some external Perl/sed/whatever magic as long as the call is made directly from Emacs and operates only on the marked region I want.

How would you automate this from Emacs?

I think the answer I'm thinking of consist in calling shell-command-on-region and replace the region by the output... But I'm not sure as to how to concretely do this.


Solution

  • This can be solved by using the command query-replace-regexp (bound to C-M-%):

    C-M-% \b[0-9][0-9]\b return \,(1+ \#&)

    The expression that follows \, would be evaluated as a Lisp expression, the result of which used as the replacement string. In the Lisp expression, \#& would be replaced by the matched string, interpreted as a number.

    By default, this works on the whole document, starting from the cursor. To have this work on the region, there are several posibilities:

    1. If transient-mark-mode is turned on, you just need to select the region normally (using point and mark);
    2. If for some reason you don't like transient-mark-mode, you may use narrow-to-region to restrict the changes to a specific region: select a region using point and mark, C-x n n to narrow, perform query-replace-regexp as described above, and finally C-x n w to widen. (Thanks to Justin Smith for this hint.)
    3. Use the mouse to select the region.

    See section Regexp Replacement of the Emacs Manual for more details.