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

大憨熊 提交于 2019-11-28 20:03:18

问题


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.


回答1:


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.




回答2:


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




回答3:


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.




回答4:


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



回答5:


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...



来源:https://stackoverflow.com/questions/2686593/emacs-adding-1-to-every-number-made-of-2-digits-inside-a-marked-region

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!