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
Since it seems like indeed there's no way to pass in arguments, the best workaround I can think of is to use an intermediate placeholder that is replaced from the command line. foo-to-bar.sed
:
s/foo/#ARG1#/
Invocation:
sed -f foo-to-bar.sed -e "s/#ARG1#/bar/g" some-file.txt
Explanation: foo
is first replaced with #ARG1#
and then with bar
passed from the command line. Note that it's important to have the -e
after -f
. Also there's nothing special about the #
delimiter, use anything that wouldn't normally appear in the file.
Best Answer
From the man page:
So you can use multiple
-e
options to build up a script out of many parts.Would first replace
foo
withbar
and then delete every line containingFOO
.