Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question
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

3 Answers 3

I would use translate command tr eg.

tr ab ba < input_file
share|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
    
@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 '
s/a/xa/g;
s/b/xb/g;
s/xa/yb/g;
s/xb/ya/g;
s/ya/a/g;
s/yb/b/g;
'

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.

share|improve this answer

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'

or

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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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