8

I would like to change all occurrences of a string (say string1) with another string (say string2) and vice-versa. To be precise I have a long document and these strings occur many times. What I currently do, is to replace string1-->string3, then string2-->string1 and finally string3-->string2.

I am wondering if there is already a function in emacs which does this. Other solutions are welcomed.

Edit: This is actually a duplicate of the question linked in the comment. But the problem is that the accepted answer of that question does not always work (see the comment below). I think it is better to wait until the author of that accepted answer corrects his/her answer or some other solution comes out. Secondly before posting my question, I googled the question and that question did not show up. I think having two duplicate questions is sometimes useful since they use different wording and if a user find the duplicate one, he/she can find the right one.

Edit 2: The accepted answer of Search/replace-like feature for swapping text seems to be fine now.

  • 4
    Possible duplicate of Search/replace-like feature for swapping text – T. Verron Oct 13 '16 at 8:37
  • @T.Verron I tried to use the accepted answer of your link to replace "This" with "that" in the scratch buffer but it does not work. – Name Oct 13 '16 at 8:52
  • Maybe I accepted too fast. Commenting the last two arguments out (backwards and region-noncontiguous-p) in the call of perform-replace makes it work here (emacs 24.3). I'll test it on emacs 25 when I get an occasion before editing the other answer. – T. Verron Oct 13 '16 at 9:05
  • @T.Verron by contrast, the other solution suggesting to use the package plur. It seems to work in this situation without problem. – Name Oct 13 '16 at 10:21
  • I have changed the accepted answer in the other question. Regarding google, yes, I too had trouble finding keywords to convey what I was trying to do. And yes, duplicates are good! blog.stackoverflow.com/2010/11/… – T. Verron Oct 14 '16 at 7:36
10

For the interactive case query-replace-regexp (C-M-%) can do this, using the relatively unknown \, for the replacement.

C-M-% \(string1\)\|\(string2\)
\,(if (equal \& "string1") "string2" "string1")

If the replacement text contains \, followed by a lisp expression, it uses the value of that expression as the replacement. In this case the expression is an "if" which takes a condition and the return value for the true and false cases.

In the comments it is suggested to use

\,(if \1 "string2" "string1")

This works because \1 will be "string1" if the pattern matches string1, and will be nil otherwise. Lisp takes any non-nil value as true. Whilst this works and is shorter, I think my answer is more useful. I think the code is more readable to someone whose lisp knowledge is limited. It has a second advantage as it still works if the "from" pattern is given as

\(string1\|string2\)

or even

string1\|string2
  • 2
    Some comment in the duplicate candidate suggested the simpler syntax \,(if \1 "string2" "string1"), using the regexp \(string1\)\|string2. – T. Verron Oct 14 '16 at 6:41
  • See the last two paragraphs of (emacs) Regexp Replace. – Basil Jan 21 '18 at 16:40
-1

Well, maybe with a macro this would be easy:

F3C-saRETC-bM-tF4. Using this macro on your question yells this result:

I would like to change all occurrences of string a (say string1) with another string (say string2) and vice-versa. To be precise I have long a document and these strings occur many times. What I currently do, is to replace string1-->string3, then string2-->string1 and finally string3-->string2.

I am wondering if there is already function a in emacs which does this. Other solutions are welcomed.

I'm transposing positions between whatever word is after an a and that word. You can later edit such macro to transpose other words as well without needing to redefine the entire macro, you can edit the macro with C-xC-kRET.

  • 1
    I don't think the question is related to transposing words. – T. Verron Oct 13 '16 at 8:41
  • @T.Verron It is, but he wants a more automatized approach, it seems. – shackra Oct 14 '16 at 22:48
  • 1
    What your macro does is exchanging (transposing) each "a" with the next word. "a string" > "string a" etc. What he wants to do is e.g. replace each "a" with "the" and each "the" with "a". – T. Verron Oct 15 '16 at 11:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.