Linux – sed “e” and “g” flags not working together

linuxsed

Given this:

echo AAA | sed -r 's/A/echo B/ge'

I get this:

Becho Becho B

I would have thought I would get "BBB". This is with GNU sed version 4.2.1. What is going on, and how can I use the execute flag, and have multiple replacements can occur on one line (from the shell, not from perl et al)?

Best Answer

The flags work together in the opposite way to what you're expecting. The documentation of /e is, for the record:

This command allows one to pipe input from a shell command into pattern space. If a substitution was made, the command that is found in pattern space is executed and pattern space is replaced with its output. A trailing newline is suppressed; results are undefined if the command to be executed contains a nul character. This is a GNU sed extension.

That is a bit tortuously written. What it means is that, after the completion of a s/// command for this line, if there was a change, the (new) line is executed as a command and its output used as the replacement for this line.

So for your given command:

echo AAA | sed -r 's/A/echo B/ge'

it first replaces each A with echo B, and then executes the result as a command. It has (roughly speaking) the same effect as:

echo AAA | sed -r 's/A/echo B/g' | sh

GNU sed does not directly support the mode you want, although you can fake it with a more complex script if desired. Alternatively, Perl's /e modifier to its s command does have the behaviour you're looking for, but with Perl expressions instead.

Related Question