qin peter
qin peter

Reputation: 359

what does the "e" modifier to the s/// command mean in GNU sed?

I have read sed manual for the s/// command. There it says:

e

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.

I don't know what is useful:

echo "1234" | sed 's/1/echo ss/e'
echo "1234" | sed 's/1/ss/'

These two commands result in the same, so what is the e modifier about?

Upvotes: 3

Views: 816

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 754190

$ printf "%s\n" 1234 2345 3456 |
> sed -e 's/\(..\)\(..\)/echo $((\1 * \2))/e'
408
1035
1904
$

This printf command echoes three 4-digit numbers on three lines. The sed script splits each line into a pair of 2-digit numbers, creates a command echo $((12 * 34)), for example, runs it, and the output (408 for the given values) is included in (as) the pattern space — which is then printed. So, for this script, the pairs of 2-digit numbers are multiplied and the result is shown.

You can get fancier if you wish:

$ printf "%s\n" 1234 2345 3456 |
> sed -e 's/\(..\)\(..\)/echo \1 \\* \2 = $((\1 * \2))/e'
12 * 34 = 408
23 * 45 = 1035
34 * 56 = 1904
$

Note the double backslash — that's rather important. You could avoid the need for that using double quotes:

printf "%s\n" 1234 2345 3456 |
sed -e 's/\(..\)\(..\)/echo "\1 * \2 = $((\1 * \2))"/e'

Beware: the notation will run the external command every time the s/// command actually makes a substitution. If you have millions of lines of data in your files, that could mean millions of commands executed.

Upvotes: 7

tripleee
tripleee

Reputation: 189527

The /e option is a GNU sed extension. It causes the result of the replacement to be passed to the shell for evaluation as a command. Observe:

vnix$ sed 's/a/pwd/' <<<a
pwd

vnix$ sed 's/a/pwd/e' <<<a
/home/tripleee

Your example caused identical behavior (echoing back exactly the replaced text) so it was a poorly chosen example.

Out of the box, the pattern space refers to the current input line, but there are ways to put something else in the pattern space. Substitution modifies the pattern space, but there are other sed commands which modify the pattern space in other ways. (For a trivial example, x swaps the pattern space with the hold space, which is basically another built-in variable which you can use for whatever you want.)

Upvotes: 2

Related Questions