I have a text 'ab' whose content is composed of a,b letter. I want to change a to b, b to a at once by using s command in ed. But if I change them step by step, as you know, all the text will be changed into only a or only b. Is there any way to change a to b and b to a at the same time?
Not natively, no -- it lacks the transliterate command you see in sed (
y) and perl (
y///) -- but you could fake it with the
transliterate command itself:
ed -s input <<< $'e !tr ab ba < %\nw\nq'
e command replaces the contents of the file with the results of the shell escape command; that command transliterates a to b and b to a and is given the current filename as input. The new file is then
written to disk; then we
Not "at the same time", but you can do it in a series of steps.
The first step is to tag all the things needing to be changed.
Second step is to change all tagged
Third step is to change all tagged
So the question then becomes
how can I tag the things to change?
There is an interesting technique which says you can use a letter
a (one of the two characters you want to swap) to do the tagging.
s/[ab]/a&/g s/aa/b/g s/ab/a/g
For this input
aaaa aaab aaba aabb abaa abab abba abbb baaa baab baba babb bbaa bbab bbba bbbb
the steps produce
aaaaaaaa aaaaaaab aaaaabaa aaaaabab aaabaaaa aaabaaab aaababaa aaababab abaaaaaa abaaaaab abaaabaa abaaabab ababaaaa ababaaab abababaa abababab bbbb bbbab bbabb bbabab babbb babbab bababb bababab abbbb abbbab abbabb abbabab ababbb ababbab abababb abababab bbbb bbba bbab bbaa babb baba baab baaa abbb abba abab abaa aabb aaba aaab aaaa
which is the desired result.
Obviously if there is a character that is known not to be in the input, for example ctrl-A, you can also do the change in 3 steps, first change all
ctrl-A, then change all
a and then change all
You do it the same as you swap two variables in
tmp = a; a = b; b = tmp ;-)
p foobar s/foo/FOO/ s/bar/foo/ s/FOO/bar/ p barfoo
FOO above with any char or text which doesn't appear in your line.