help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: TIL about string-rectangle


From: Tim Landscheidt
Subject: Re: TIL about string-rectangle
Date: Wed, 30 Dec 2020 21:37:44 +0000
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)

Skip Montanaro <skip.montanaro@gmail.com> wrote:

> I needed to replace the first comma on each line of a CSV file so I
> could more conveniently sort by the first field (date, arranged as
> MM/DD/YYYY). After a bit of fussing around, I got it squared away with
> query-replace-regexp, did my sort, then needed to revert the
> replacement text back to comma. Unfortunately, there were a few other
> instances of the replacement text elsewhere in the file which caused
> problems. (If I'd had my thinking cap on I would have checked before
> doing the original replace, but it seems I was wearing my dunce
> cap...) Poking around for help from Emacs against a future need, I
> discovered replace-rectangle, which turns out to be an alias for
> string-rectangle (bound to C-x r t). It looks to be quite handy when
> you need to replace text within a rectangle. It's sort of (but not
> quite) like narrow-to-region + query-replace(-regexp)?. It doesn't
> query for a string to replace. It simply replaces the rectangle's
> contents with the given string on each line.

For complex sorts, I once wrote a function that enhances
sort-regexp-fields (and needs a docstring and comments that
I could understand after eight years):

| (defun tl-sort-regexp-fields (reverse record-regexp key-regexp beg end)
|   "Extended sort function."
|   (interactive "P\nsRegexp specifying records to sort: \nsRegexp specifying 
key within record: \nr")
|   (if (string-match "\\`\\(?:-\\\\[1-9]\\|\\(?:-?\\\\[1-9]\\)\\{2,\\}\\)\\'" 
key-regexp)
|       (let
|           ((i (length key-regexp)))
|         (while (> i 0)
|           (let ((key-reverse (and (> i 2) (= (aref key-regexp (- i 3)) ?-)))
|                 (key (substring key-regexp (- i 2) i)))
|             (sort-regexp-fields (if reverse (not key-reverse) key-reverse) 
record-regexp key beg end)
|             (if key-reverse
|                 (setq i (- i 1)))
|             (setq i (- i 2)))))
|     (sort-regexp-fields reverse record-regexp key-regexp beg end)))

Basically, you can select a region of a CSV file, then enter
(untested)
"^,\([0-9][0-9]\)/\([0-9][0-9]\)/\([0-9][0-9][0-9][0-9]\),.*$"
at the first prompt and "\3\1\2" at the (incorrectly named)
second, and then the lines would be sorted by year, month,
day.  You can reverse the order for individual keys by pre-
pending a "-".  It takes advantage of the (not guaranteed?)
fact that Emacs's sort functions are stable, i. e. the order
of lines with the same key is not changed.

If someone wants to clean that up and include it either as a
separate function in Emacs or semi-backwards-compatibly in
sort-regexp-fields, much appreciated.

Tim



reply via email to

[Prev in Thread] Current Thread [Next in Thread]