0

enter code hereWhat would be the most efficient way to change the format of a list of dates like this in Emacs:

|Bob|1966/08/20|2023/05/19|
|Janice|1964/09/18|2023/05/19|

To this:

|Bob|<1966-08-20>|<2023-05-19>|
|Janice|<1964-09-18>|<2023-05-19>|

Would it be most efficient to use replace-regexp, rectangles, macros, the multiple cursor package, or something else?

In ed I am able to effect the change with two simple regular expressions:

g/\//s//-/g
g/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/s//<&>/g
4
  • 1
    replace-regexp seems to me to be be the natural fit here. Commented May 19, 2023 at 14:20
  • The first one should be replace-regexp RET / RET - and assumes that there are no other slashes around, but indeed, that's a perfectly good way to proceed. You need to be at the beginning of the buffer. Commented May 19, 2023 at 15:40
  • You deleted your comment! And this after (or during the time) I changed the answer to refer to it and added my previous comment :-) Ah, well - these things happen... Commented May 19, 2023 at 15:43
  • Sorry Nick. Self doubt crept in. Commented May 20, 2023 at 11:16

1 Answer 1

1

One way to do what you want:

M-: (replace-regexp "\\([0-9]\\{4\\}\\)/\\([0-9]\\{2\\}\\)/\\([0-9]\\{2\\}\\)" "<\\1-\\2-\\3>" nil (point-min) (point-max))

This looks more complicated than it is because of the escaped backslashes: you could do M-x replace-regexp and then type the regexp in, in which case you'd only type a single backslash.

The regexp matches four digits, followed by a slash, followed by two digits, followed by a slash, followed by two digits. The groups of digits (year, month, day) are remembered (because they are inside \( ... \) ) and numbered 1, 2 and 3 resp. The replacement text then uses them by referring to them as \1, \2 and \3 (again the backslashes have to be doubled in lisp code).

The function is applied to a region (by default, starting from the current position of the cursor (the point) and going to the end of the buffer). Here we specify the beginning of the buffer ((point-min)) and the end of the buffer ((point-max)) so that the whole buffer is scanned).

There are many other ways to do this (e.g. two applications of replace-regexp with suitably modified versions of your ed regexps is another possibility - which I now see you have added in a comment!).

Regexps can be daunting and are overused in many cases, but there is no question that they are useful. See the Emacs manual, chapter Searching and Replacement, for more info. And for even more, see the Emacs Lisp Reference manual, chapter Searching and Matching.

1
  • Beautifully elegant solution. Commented May 19, 2023 at 15:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.