I am trying to emulate a replace command which swaps two characters, with a sed script, but the obvious choice:

sed -e 's/a/b/g' -e 's/b/a/g' 

does no work. Can you point me how to do it correctly?

  • 3
    Since none of the answers say so, I'll just note here that your attempt isn't working because you're first swapping every a to b and then swapping every b to a. So aaabbb would go aaabbb --> bbbbbb --> aaaaaa. sed runs its commands in sequence, rather than all at once. – evilsoup Nov 10 '13 at 20:38

I would use translate command tr eg.

tr ab ba < input_file
| improve this answer | |
  • thanks X Tian. Is there any advantages of using 'tr ab ba' over 'replace a b b a' ? – Mitten Nov 10 '13 at 14:13
  • 1
    @Mitten you're the one who specifically asked for a non replace solution, you tell us :). – terdon Nov 10 '13 at 15:33
  • 2
    The advantage for me is that I have the tr command and know it but not the replace command. If I've answered you question could you please tick it. tks – X Tian Nov 10 '13 at 17:23

If you only want to replace individual characters, not longer strings, use

sed -e 'y/ab/ba/'

or the equivalent tr command from X Tian's answer. For arbitrary strings, you have to work harder:

If there is any character that does certainly not occur in the input, such as # (even a control character will do), you can use something like

sed -e 's/a/#/g;s/b/a/g;s/#/b/g;'

Alternatively, you can do some tricks with prefixing:

sed -e '

that is: prefix every a and b with x (which means: not yet modified), replace xa by yb and vice versa (where y means: modified), and remove all prefixes.

| improve this answer | |
  • Nice prefixing trick! – Wildcard May 4 '16 at 0:55

If you have a spare character you can do the suggestion of Uwe.

If you really only need to replace a single character and you do not necessarily need sed, use tr as suggested by XTian.

If you don't need sed and you might replace longer sequences without needing a spare character you might go with something like that:

perl -le '%ex=(a=>"b",b=>"a"); $keys=join("|",keys(%ex)); $text="abba"; $text=~s/$keys/$ex{$&}/eg; print $text'


ruby -e 'ex={"a"=>"b","b"=>"a"}; puts "abba".gsub(/(#{ex.keys.join("|")})/,ex)'
| improve this answer | |

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.