Mastering Advanced sed Substitutions in Linux
The Linux operating system manages complex string transformations
primarily through sed (stream editor), a non-interactive
utility that parses and transforms text streams line by line. This
article explores how sed processes advanced substitutions,
detailing the mechanics of backreferences, custom delimiters, case
conversion switches, address-restricted matching, and pattern space
manipulation to execute precise, high-performance text transformations
directly from the command line.
Core Substitution Syntax and Delimiters
The standard syntax for text replacement in sed is
s/regexp/replacement/flags. When the stream editor reads a
line into its active working memory—known as the pattern space—it
evaluates the regular expression and applies the transformation.
By default, forward slashes (/) delimit the command.
However, when transforming paths or URLs, escaping slashes leads to
unreadable patterns. In Linux, sed allows any single
character following the s to act as an alternate
delimiter:
sed 's|/usr/local/bin|/usr/bin|g' input.txt
sed 's#/var/log#/opt/logs#g' input.txtCommon flags appended to the end of the substitution include:
g: Global replacement across the entire line.p: Prints the pattern space if a successful substitution occurred (often paired with the-nsilence flag).Iori: Enables case-insensitive matching.2(or any integer n): Replaces only the n-th occurrence of the match on each line.
Backreferences and Pattern Reordering
Advanced transformations frequently require reordering strings or
injecting captured data into new templates. In POSIX basic regular
expressions (BRE), parentheses must be escaped (\( and
\)), while extended regular expressions (ERE, enabled via
sed -E) permit unescaped parentheses.
Captured patterns are mapped sequentially to variables
\1 through \9:
# Swapping key-value pairs (Extended Regex)
sed -E 's/([a-zA-Z_]+)=([0-9]+)/\2=\1/' config.envThe ampersand (&) represents the entire matched
pattern, preventing redundant typing when wrapping or appending
text:
# Surrounding any 4-digit number with square brackets
sed -E 's/[0-9]{4}/[&]/g' report.txtIn-Place Case Conversions
GNU sed natively supports escape sequences within the
replacement field to manipulate character casing dynamically:
\U: Converts subsequent replacement characters to uppercase until\Eis encountered.\L: Converts subsequent replacement characters to lowercase until\Eis encountered.\u: Capitalizes only the immediately following character.\l: Lowercases only the immediately following character.
This functionality enables rapid data normalization:
# Capitalizing the first letter of each word
sed -E 's/\b([a-z])/\u\1/g' names.txt
# Uppercasing only the domain component of an email address
sed -E 's/@([a-z0-9.-]+)/@\U\1\E/g' users.csvTargeted Transformations Using Addresses
Rather than applying substitutions globally, sed can
restrict string changes to specific lines using line numbers, regex
contexts, or address ranges.
# Apply substitution only to line 42
sed '42 s/DEBUG/INFO/' app.log
# Apply substitution between a start tag and an end tag
sed '/<config>/, /<\/config>/ s/enabled=false/enabled=true/' settings.xml
# Invert execution: replace text on all lines EXCEPT those matching a pattern
sed '/^#/! s/localhost/127.0.0.1/' hosts.txtMulti-Line Transformations via Pattern and Hold Spaces
For operations spanning multiple lines, sed utilizes two
storage buffers: the pattern space (temporary working
buffer) and the hold space (persistent staging
buffer).
Commands like N append the next line of input to the
current pattern space, separated by an embedded newline
(\n), allowing cross-line substitutions that single-pass
tools cannot handle natively:
# Join lines where a trailing backslash exists and remove the backslash
sed -E ':loop; /\\$/ { N; s/\\\n//; b loop }' script.shIn this command, a label (:loop) is declared. If a
backslash is found at the end of a line (/\\$/),
N pulls the subsequent line into the pattern space, the
substitution removes the backslash and newline, and b loop
branches back to check for further contiguous continuations.