Editing A Column of Numbers

Alex Schroeder has an interesting post on editing a column of numbers. The problem is that given some text such as

|[[...]]     |   1 |          6563|     3796|   |[[...]] | — |
|[[...]]     | 1/3 |          2315|     1259|   |[[...]] | — |
|[[...]]     | 1/3 |           159|      607|   |[[...]] | — |
|[[...]]     | 1/3 |           159|      597|   |[[...]] | — |

add 56 to the numbers in the third column. Schroeder's solution is to use query-replace-regexp with a complicated regular expression that selects the numbers in the third column and replaces them with

\,(+ 56 \#2)

That's a nice solution and has the virtue of using only core Emacs functionality so that it will work with any Emacs. The only problem is that nasty regular expression. It's not really that hard but has lots of room for error and will probably take most people a couple of tries to get right.

Later, I stumbled upon a post from the invaluable Mickey over at Mastering Emacs on iedit that looked like it might do the job in an easier way. iedit-mode is much like Magnar Sveen's mark-multiple package. They both allow you to mark identical pieces of text and then modify them all at once. The difficulty for the problem at hand is that the numbers are not the same and neither iedit nor mark-multiple work with regular expressions.

Sveen, however, does have a wonderful solution with his spectacular multiple-cursors package. It has a mode that allows you to select a rectangle and then operate on each line of the rectangle together. You can see a similar example in operation by watching Sveen's Emacs Rocks! Episode 13 (it's at the end of the video). The idea is to select the numbers in the third column and edit them into a sexpr that adds 56. For example, the 6563 in the first row becomes (+ 56 6563). With multiple-cursors all the rows are changed in parallel.

Finally, we call eval-and-replace to replace the sexprs with their values. This is a truly beautiful solution: quick, easy, and hard to get wrong. Of course, you do have to load extra packages. First you need multiple-cursors. That's an easy ELPA load from Marmalade and something every Emacs expert should have in their toolkit. You'll also need eval-and-replace. That function is available in many Emacs predefined configurations such as the the Emacs starter kit but it's definition is simple. Here's my version: it's only 5 lines so you can just grab it and plop it into your .emacs or init.el.

The bottom line is that you can always solve problems like this using Schroeder's solution in any Emacs installation but if you have a little bit of extra help loaded, the solution is trivial.

This entry was posted in General and tagged . Bookmark the permalink.