sed "e" and "g" flags not working together

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.


You are getting multiple replacement, but you don't get multiple executions. The pattern is executed once all the replacements have been made.

Without the e flag the result of

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

is

echo Becho Becho B

So that's the command line that's executed if you do include the e flag, which is equivalent to

echo 'Becho Becho B'

To get 'BBB' from 'AAA' using GNU sed's 's' command with the 'e' flag, one can do this:

echo AAA | sed -re 's/A/echo -n B;/ge'

The 'AAA' is substituted to 'echo -n B;echo -n B; echo -n B;', which, when eventually executed, leads to 3 sequentially running echo commands, one for each of the global matches. The '-n' omits the linefeed characters from echo's output, making the 'B's end up on one line (but sed appends one linefeed by itself when finally printing the pattern space).

Tags:

Linux

Sed