How to switch the first letters of two words

perlsed

$ echo 'foo bar' | sed SOMEMAGIC
boo far
$ echo 'one two' | sed SOMEMAGIC
tne owo

Q: in general, how can I replace the "b" from the "bar" to the "f" of the "foo"? And in reverse too, replace the "f" from the "foo" to the "b" of the "bar".

Best Answer

You need to make use of capture groups. Capture (1) the first letter of a word, (2) everything until the first letter of the second word, (3) first letter of the second word and swap (3) and (1).

In the examples below, it's assumed that the line starts with a non-blank character

You could say:

sed 's/\(.\)\([^ ]* \)\(.\)/\3\2\1/'

or

sed -r 's/(.)([^ ]* )(.)/\3\2\1/'

For example,

$ echo 'foo bar' | sed -r 's/(.)([^ ]* )(.)/\3\2\1/'
boo far
$ echo 'one two' | sed -r 's/(.)([^ ]* )(.)/\3\2\1/'
tne owo

The following would also handle cases like spaces at the beginning of the line, and multiple spaces between the two words:

sed -r 's/([^ ])([^ ]* +)(.)/\3\2\1/'

A corresponding perl expression would be:

perl -pe 's/(\S)(\S+\s+)(\S)/$3$2$1/'

Examples:

$ echo 'one two' | perl -pe 's/(\S)(\S+\s+)(\S)/$3$2$1/'
tne owo
$ echo 'one two' | perl -pe 's/(\S)(\S+\s+)(\S)/$3$2$1/'
tne owo
$ echo 'foo bar' | perl -pe 's/(\S)(\S+\s+)(\S)/$3$2$1/'
boo far
$ echo '   one     two' | perl -pe 's/(\S)(\S+\s+)(\S)/$3$2$1/'
   tne     owo
Related Question