all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Transposing Regular Expression
@ 2009-11-11 17:25 jrwats
  2009-11-11 20:51 ` harven
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: jrwats @ 2009-11-11 17:25 UTC (permalink / raw)
  To: help-gnu-emacs

Perl provides the transpose operator:
=~ tr/abc/xyz/	not really a regular expression, but exchanges 'x' for
'a', 'y' for 'b', and 'z' for 'c' in the source string.

My question is how to accomplish this in emacs.  When only needing to
tranpose 2 characters that need to replace each other, (the equivalent
perl expression woud be =~ tr/ab/ba/ as an example, I could simply
regexp replace 'a' with a unique letter or symbol, maybe '$' for
instance, then replace all b's with a's and all $'s with b's.  This
obviously becomes unweildy after we start transposing more than 2
characters.  My question is, now that emacs provides fancy regexp
replace clauses: \# for the number match, and arbitrary lisp
expressions \,(some-lisp), etc, is there a way to accomplish this in
one fell swoop via a very crazy regular expression find-replace?  Also
is there a list of meaningful  regular expression search escape
characters somewhere (like \#) ?


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Transposing Regular Expression
  2009-11-11 17:25 Transposing Regular Expression jrwats
@ 2009-11-11 20:51 ` harven
  2009-11-11 21:45 ` Andreas Politz
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: harven @ 2009-11-11 20:51 UTC (permalink / raw)
  To: help-gnu-emacs

jrwats <jrwats@gmail.com> writes:

> Perl provides the transpose operator:
> =~ tr/abc/xyz/	not really a regular expression, but exchanges 'x' for
> 'a', 'y' for 'b', and 'z' for 'c' in the source string.
>
> My question is how to accomplish this in emacs.  When only needing to
> tranpose 2 characters that need to replace each other, (the equivalent
> perl expression woud be =~ tr/ab/ba/ as an example, I could simply
> regexp replace 'a' with a unique letter or symbol, maybe '$' for
> instance, then replace all b's with a's and all $'s with b's.  This
> obviously becomes unweildy after we start transposing more than 2
> characters.  My question is, now that emacs provides fancy regexp
> replace clauses: \# for the number match, and arbitrary lisp
> expressions \,(some-lisp), etc, is there a way to accomplish this in
> one fell swoop via a very crazy regular expression find-replace?  Also
> is there a list of meaningful  regular expression search escape
> characters somewhere (like \#) ?

The emacs manual gives the following snippet for swapping two values.

     M-x replace-regexp <RET> \(x\)\|y <RET>
     \,(if \1 "y" "x") <RET>

Note that you can swap two words by the same method. This is not exactly
what you are looking for though. 

There are many functions that have been devised to swap values
according to an alist, e.g. for converting accents from iso8859-1 to html.
These can be easily adapted to get a command emulating tr.

Cheers


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Transposing Regular Expression
  2009-11-11 17:25 Transposing Regular Expression jrwats
  2009-11-11 20:51 ` harven
@ 2009-11-11 21:45 ` Andreas Politz
  2009-11-12  6:40 ` LanX
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Andreas Politz @ 2009-11-11 21:45 UTC (permalink / raw)
  To: help-gnu-emacs

jrwats <jrwats@gmail.com> writes:

> Perl provides the transpose operator:
> =~ tr/abc/xyz/	not really a regular expression, but exchanges 'x' for
> 'a', 'y' for 'b', and 'z' for 'c' in the source string.
>
> My question is how to accomplish this in emacs.  When only needing to
> tranpose 2 characters that need to replace each other, (the equivalent
> perl expression woud be =~ tr/ab/ba/ as an example, I could simply
> regexp replace 'a' with a unique letter or symbol, maybe '$' for
> instance, then replace all b's with a's and all $'s with b's.  This
> obviously becomes unweildy after we start transposing more than 2
> characters.  My question is, now that emacs provides fancy regexp
> replace clauses: \# for the number match, and arbitrary lisp
> expressions \,(some-lisp), etc, is there a way to accomplish this in
> one fell swoop via a very crazy regular expression find-replace?  Also
> is there a list of meaningful  regular expression search escape
> characters somewhere (like \#) ?

You can use literal backreferences (e.g. \1) in the replacement part of
interactive uses of replace-regexp.  Combine that with expressions \,
and you could write a c-compiler in emacs-regexp/elisp.

The regular expression syntax is described in the elisp manual.

(info "(elisp)Regular Expressions")

-ap





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Transposing Regular Expression
  2009-11-11 17:25 Transposing Regular Expression jrwats
  2009-11-11 20:51 ` harven
  2009-11-11 21:45 ` Andreas Politz
@ 2009-11-12  6:40 ` LanX
  2009-11-16 12:16 ` Andreas Röhler
       [not found] ` <mailman.10804.1258373854.2239.help-gnu-emacs@gnu.org>
  4 siblings, 0 replies; 7+ messages in thread
From: LanX @ 2009-11-12  6:40 UTC (permalink / raw)
  To: help-gnu-emacs

Hi

I'm a newbie in elisp, but this works for me:

--------- tested in M-x ielm
ELISP> (defun pl-tr (STRING FROM TO)
	 "perlish transpose"
	 (replace-regexp-in-string
	  (concat "\[" FROM "\]")
	  (lambda (s)
	    (string (elt TO (search s FROM))))
	  STRING)
	 )
pl-tr
ELISP> (pl-tr "fedcba" "bcd" "BCD")
"feDCBa"
-----------------------------------------------

HTH

Cheers
  Rolf


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Transposing Regular Expression
  2009-11-11 17:25 Transposing Regular Expression jrwats
                   ` (2 preceding siblings ...)
  2009-11-12  6:40 ` LanX
@ 2009-11-16 12:16 ` Andreas Röhler
       [not found] ` <mailman.10804.1258373854.2239.help-gnu-emacs@gnu.org>
  4 siblings, 0 replies; 7+ messages in thread
From: Andreas Röhler @ 2009-11-16 12:16 UTC (permalink / raw)
  To: jrwats; +Cc: help-gnu-emacs

jrwats wrote:
> Perl provides the transpose operator:
> =~ tr/abc/xyz/	not really a regular expression, but exchanges 'x' for
> 'a', 'y' for 'b', and 'z' for 'c' in the source string.
> 
> My question is how to accomplish this in emacs.  When only needing to
> tranpose 2 characters that need to replace each other, (the equivalent
> perl expression woud be =~ tr/ab/ba/ as an example, I could simply
> regexp replace 'a' with a unique letter or symbol, maybe '$' for
> instance, then replace all b's with a's and all $'s with b's.  This
> obviously becomes unweildy after we start transposing more than 2
> characters.  My question is, now that emacs provides fancy regexp
> replace clauses: \# for the number match, and arbitrary lisp
> expressions \,(some-lisp), etc, is there a way to accomplish this in
> one fell swoop via a very crazy regular expression find-replace?  Also
> is there a list of meaningful  regular expression search escape
> characters somewhere (like \#) ?
> 


IIUC you are going to change strings.

That's a simple task then with no need to employ
\# for the number match ore other advanced features.

Interactivly just call

M-x query-replace - putting in your strings at the prompt.

From a program use for example

(while
  (search-forward "abc" nil t 1)
  (replace-match "xyz"))


Andreas

--
https://code.launchpad.net/s-x-emacs-werkstatt/
http://bazaar.launchpad.net/~a-roehler/python-mode/python-mode.el/





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Transposing Regular Expression
       [not found] ` <mailman.10804.1258373854.2239.help-gnu-emacs@gnu.org>
@ 2009-11-16 16:28   ` jrwats
  2009-11-17  2:13     ` LanX
  0 siblings, 1 reply; 7+ messages in thread
From: jrwats @ 2009-11-16 16:28 UTC (permalink / raw)
  To: help-gnu-emacs

> IIUC you are going to change strings.
>
> That's a simple task then with no need to employ
> \# for the number match ore other advanced features.
>
> Interactivly just call
>
> M-x query-replace - putting in your strings at the prompt.
>
> From a program use for example
>
> (while
>   (search-forward "abc" nil t 1)
>   (replace-match "xyz"))
That's not exactly what I'm looking for as I really need 2 words/
characters to be swapped.  For instance, swapping "true" and "false"
in a region.  Replacing all the "true"s with "false"s will yield a 1/2
correct answer but there's no way to replace the old false's anymore.
LanX's solution appears to do the correct thing regarding an actual
Perl-style transpose, and seeems like it could easily be altered to
work on a region.  The quickest solution for the simple 2-way swap was
definitely the back reference (example provided by harven).




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Transposing Regular Expression
  2009-11-16 16:28   ` jrwats
@ 2009-11-17  2:13     ` LanX
  0 siblings, 0 replies; 7+ messages in thread
From: LanX @ 2009-11-17  2:13 UTC (permalink / raw)
  To: help-gnu-emacs

> That's not exactly what I'm looking for as I really need 2 words/
> characters to be swapped.  For instance, swapping "true" and "false"
> in a region.

OK let's talk perl to understand ... Thats what you want?

perl -e '
$_="EXAMPLE true EXAMPLE false EXAMPLE";
%trans=(true=>"false");
%trans=(%trans,reverse %trans);
$pattern=join "|",keys %trans;
s/($pattern)/$trans{$1}/g;
print "OUTPUT: $_";
'

OUTPUT: EXAMPLE false EXAMPLE true EXAMPLE

(please note: if you don't just want a dual swap but a more
complicated permutation, skip the "reverse" part and provide %trans as
needed like e.g. (1=>2, 2=>3, 3=>1))

You can easily adjust the lisp code I gave you to do that, you need to
change the lambda to do a hash look up and call it within one of the
region-replace functions!

Though for me the corresponding lisp code for hashes seem a little
lengthy...

(I now there are alists, but I leave this solution to others)

So why don't you just pipe a region thru the perl script above?

Typing
C-u M-|
perl -pe '
%trans=(true=>"false");
%trans=(%trans,reverse %trans);
$pattern=join "|",keys %trans;
s/($pattern)/$trans{$1}/g;
'

Can be easily adjusted to do what you want.

And if you type C-x ESC ESC you get the corresponding lisp wrapper for
free
---------
(shell-command-on-region (region-beginning) (region-end) "perl -pe '
%trans=(true=>\"false\");
%trans=(%trans,reverse %trans);
$pattern=join \"|\",keys %trans;
s/($pattern)/$trans{$1}/g;
'
" (quote -) (quote -) nil t)
--------


Couldn't be easier... and the call overhead to perl is really not
observable...

HTH
  LanX


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-11-17  2:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-11 17:25 Transposing Regular Expression jrwats
2009-11-11 20:51 ` harven
2009-11-11 21:45 ` Andreas Politz
2009-11-12  6:40 ` LanX
2009-11-16 12:16 ` Andreas Röhler
     [not found] ` <mailman.10804.1258373854.2239.help-gnu-emacs@gnu.org>
2009-11-16 16:28   ` jrwats
2009-11-17  2:13     ` LanX

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.