From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Tim Landscheidt Newsgroups: gmane.emacs.help Subject: Re: TIL about string-rectangle Date: Wed, 30 Dec 2020 21:37:44 +0000 Organization: http://www.tim-landscheidt.de/ Message-ID: <87a6tvkmaf.fsf@passepartout.tim-landscheidt.de> References: Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="33954"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) Cc: help-gnu-emacs@gnu.org To: Skip Montanaro Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Wed Dec 30 22:39:17 2020 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kujBd-0008jP-H9 for geh-help-gnu-emacs@m.gmane-mx.org; Wed, 30 Dec 2020 22:39:17 +0100 Original-Received: from localhost ([::1]:47804 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kujBc-0003Fp-KA for geh-help-gnu-emacs@m.gmane-mx.org; Wed, 30 Dec 2020 16:39:16 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:36834) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kujAH-0003ES-FY for help-gnu-emacs@gnu.org; Wed, 30 Dec 2020 16:37:53 -0500 Original-Received: from andalucia.tim-landscheidt.de ([2a01:4f8:1c1c:d4d0::1]:44626) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kujAD-0004ac-PP for help-gnu-emacs@gnu.org; Wed, 30 Dec 2020 16:37:53 -0500 Original-Received: from dslb-090-186-126-124.090.186.pools.vodafone-ip.de ([90.186.126.124]:60722 helo=passepartout.tim-landscheidt.de) by andalucia.tim-landscheidt.de with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1kujA9-0005fq-B7; Wed, 30 Dec 2020 22:37:45 +0100 In-Reply-To: (Skip Montanaro's message of "Wed, 30 Dec 2020 14:59:25 -0600") Received-SPF: pass client-ip=2a01:4f8:1c1c:d4d0::1; envelope-from=tim@tim-landscheidt.de; helo=andalucia.tim-landscheidt.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "help-gnu-emacs" Xref: news.gmane.io gmane.emacs.help:126924 Archived-At: Skip Montanaro 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