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
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
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
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/
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