开发者

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 fr开发者_JS百科om 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.


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.


Emacs' column editing mode is what you need.

  • Activate it typing M-x cua-mode.

  • Go to the beginning of the rectangle (leave cursor on character 3) and press C-RET.

  • Go to the end of the rectangle (leave cursor on character 7). You will be operating on the highlighted region.

  • Now press M-i which increments all values in the region.

You're done.! remove dead ImageShack links


It doesn't protect against 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)))))))

Oh, and it operates on the region. If you want the entire file, then you replace b and e with (point-min) and nil.


Moderately tested; use M-: and issue the following command:

(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))))))


I managed to get it working in a different way using the following (my awk-fu ain't strong so it probably can be done in a simpler way):

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

but I lost my indentation in the process : )

Seeing all these answers, I can't help but have a lot of respect for Emacs...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜