sed Capture Groups and Backreferences
sed capture groups remember parts of the match so the replacement can reuse them with \1 through \9 and & for the entire match.
Backreferences turn substitution into reformatting. Capture pieces of a line with groups, then rearrange or wrap them in the replacement.
What it does
Parentheses define capture groups in the pattern. In the replacement, \1 to \9 expand to the captured text in order, and & expands to the whole match. Under basic regex the groups are \( \); under -E they are plain ( ).
Common usage
# swap two columns
echo "Doe,John" | sed -E 's/(.+),(.+)/\2 \1/' # John Doe
# wrap each version number in quotes
sed -E 's/([0-9]+\.[0-9]+\.[0-9]+)/"\1"/' file
# duplicate the match with &
echo "42" | sed 's/[0-9]*/<&>/' # <42>Options
| Token | What it expands to |
|---|---|
| \1 .. \9 | The text captured by group 1 through 9 |
| & | The entire matched substring |
| \& | A literal ampersand in the replacement |
| \( \) (BRE) | Define a group in basic regex mode |
| ( ) with -E | Define a group in extended regex mode |
| \U \L (GNU) | Uppercase or lowercase the following text |
In CI
Backreferences are how you bump a version: capture the parts, increment one, and reassemble. The \U and \L case-conversion escapes are GNU extensions, so do not rely on them on macOS BSD sed.
Common errors in CI
sed: -e expression #1, char N: invalid reference \2 on `s' command's RHS means the replacement names a group the pattern never captured. A common cause is using ( ) without -E in BRE mode, where parentheses are literal, so group \1 does not exist.