/flags/sed/sed-e-multiple-expressions
sed -e: run several expressions in one sed command
- tool
- sed
- command
- sed
- flag
- -e SCRIPT, --expression=SCRIPT
- default
- not needed for a single script (the first non-option argument is the script)
sed -e 's/a/A/' -e 's/80/90/' file runs both substitutions, in order, on every line, in a single pass over the file. Each -e adds an expression to the script; sed joins them with newlines. With only one expression -e is optional, but it becomes necessary to give several expressions, to mix inline expressions with -f script.sed, or when the script itself starts with -.
Several -e vs a semicolon
printf 'host=a\nport=80\n' > app.conf
sed -e 's/a/A/' -e 's/80/90/' app.conf
echo '--- same with ;'
sed 's/a/A/; s/80/90/' app.conf
echo '--- order matters'
echo a | sed -e 's/a/b/' -e 's/b/c/'Output
host=A port=90 --- same with ; host=A port=90 --- order matters c
For substitutions both forms are identical. Each expression sees the line as the previous one left it, so the third command turns a into c.
Where -e and ; differ: a, i, c
The text of a, i and c (GNU one-line form) runs to the end of the line, semicolons included. A separate -e ends it:
printf 'host=a\nport=80\n' > app.conf
sed '1a added; s/80/90/' app.conf
echo '--- separate -e'
sed -e '1a added' -e 's/80/90/' app.confOutput
host=a added; s/80/90/ port=80 --- separate -e host=a added port=90
In the first command s/80/90/ became part of the appended text and never ran. The same rule applies to r and w file names and to b/t labels on BSD sed. More on a and i in sed insert a line after a match.
Ways to pass a script
| Form | Use it when |
|---|---|
| sed 'expr' file | One expression; -e is optional |
| sed -e 'e1' -e 'e2' file | Several expressions, especially with a, i, c, r, w |
| sed 'e1; e2' file | Short scripts of s, d, p commands |
| sed -f script.sed file | Long scripts kept in a file, one command per line |
| sed -f a.sed -e 'e2' file | Mix a script file with extra expressions; -e is required |
| sed -e '-x' (rare) | A script starting with a dash must follow -e |
Options apply to all expressions
-n, -E, -i and -s are global: sed -E -e 's/a+/X/' -e 's/b+/Y/' uses extended regex for both expressions. There is no way to give one expression different options; split it into two sed commands in a pipe if needed.
Pitfalls
- Quoting. Quote every expression separately.
sed -e s/a b/c/passesb/c/as a file name. - Error positions. Messages such as
-e expression #2, char 3: unterminated `s' commandcount expressions from 1, which tells you which-eis wrong; see unterminated s command. - Splitting one command. GNU sed allows a classic
a\across two-eoptions (-e '1a\' -e 'text'), but this is easy to get wrong; prefer the one-line form or a script file. - Portability. Multiple
-eoptions are POSIX and work the same on macOS.
FAQ
Is sed -e 'a' -e 'b' the same as sed 'a; b'?
For s, d, p and most commands, yes: several -e options are joined with newlines into one script, and a semicolon also separates commands. They differ for a, i, c, r, w and labels, whose argument runs to the end of the line, so only a newline or a new -e ends them.
When is -e required?
When the script starts with a dash, when you pass several expressions, or when you also use -f. With a single expression and no -f, sed takes the first non-option argument as the script and -e is optional.
In what order do multiple -e expressions run?
In the order given, for each line. The output of the first expression is the input of the second on the same line, so sed -e 's/a/b/' -e 's/b/c/' turns a into c.