linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Simulator
  • Knowledge base
  • Interview prep
Index
Categories
All entries
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
home/linux/kb/Commands/cmd-sed

kb/commands ── Commands ── intermediate

sed: stream editor

sed is a stream editor: it applies commands (`s/a/b/`, `d`, `p`, ...) to each line. `-i` edits a file in place; `-E` enables ERE; the address range `/start/,/end/` filters a block. Hold space is a second buffer.

view as markdownaka: sed, stream-editor, sed-command

Why sed

When you need to rewrite lines in a stream (a log, a config file, command output), sed is the fastest tool: one command, no temporary files, no Python. It works line by line, without buffering the entire input into memory. It fits naturally in pipelines and find -exec.

If the task goes beyond per-line substitution, reach for [[cmd-awk|awk]] or Python.

Basic syntax

sed [OPTIONS] 'SCRIPT' [FILE...]
sed [OPTIONS] -f script.sed [FILE...]

Without a file argument, sed reads stdin. The script is a set of commands separated by ; or -e. By default, sed prints every processed line unless you suppress output with -n.

The s command: substitution

The most common command:

bash
sed 's/old/new/' file.txt        # first match per line
sed 's/old/new/g' file.txt       # all matches (global)
sed 's/old/new/2' file.txt       # second match only
sed 's/old/new/gi' file.txt      # global + case-insensitive

The delimiter does not have to be /, which is convenient for paths:

bash
sed 's|/old/path|/new/path|g' file
sed 's#http://#https://#g' urls.txt

-E for ERE

By default sed uses BRE, like grep without -E. That means +, ?, (, ), {, } must be escaped. Use -E (or -r in GNU sed):

bash
sed -E 's/(error|warn): (.*)/[\1] \2/' app.log

Back-references \1, \2 work in BRE too, but in BRE the parentheses must be written \(\).

In-place editing with -i

bash
sed -i 's/foo/bar/g' file.txt           # GNU sed
sed -i.bak 's/foo/bar/g' file.txt       # with backup file.txt.bak
sed -i '' 's/foo/bar/g' file.txt        # macOS BSD sed - empty extension is required

Cross-platform trouble: GNU sed -i accepts an optional suffix attached directly (sed -i.bak), while BSD sed requires a space and a mandatory suffix (sed -i '' ...). On macOS, installing gsed via brew is the usual workaround.

Addressing: where to apply a command

bash
sed '5d' file.txt                # delete line 5
sed '5,10d' file                 # delete lines 5-10
sed '/^#/d' file                 # delete comment lines
sed '/start/,/end/d' file        # delete block from start to end inclusive
sed '$d' file                    # delete the last line
sed '1,/^$/d' file               # delete from the start to the first blank line
sed -n '/ERROR/p' file           # print only ERROR lines (like grep)

Address ranges are particularly useful: they let you cut sections out of configs or filter log blocks between markers.

Commands other than s

CommandWhat it does
ddelete (do not print) the current line
pprint (meaningful with -n)
qquit immediately
=print the line number
i\TEXTinsert TEXT before the line
a\TEXTappend TEXT after the line
c\TEXTreplace the entire line with TEXT
y/abc/ABC/character-by-character transliteration (like tr)
r FILEinsert the contents of FILE after the matching line
w FILEwrite matching lines to FILE
bash
sed '/^server {/i\# auto-managed' nginx.conf  # insert comment before each server block
sed -n '5,10p' file                            # faster than `head -10 | tail -6`
sed '0,/foo/{s/foo/bar/}' file                 # replace only the first foo in the file

Multi-line: pattern space and hold space

sed works with two buffers:

  • pattern space: the current line (the default working area)
  • hold space: secondary storage, persists between line iterations

Commands that move data between them:

  • h: copy pattern to hold (overwrites)
  • H: append pattern to hold (with \n)
  • g: copy hold to pattern (overwrites)
  • G: append hold to pattern
  • x: swap

The classic trick for reversing line order (like tac):

bash
sed '1!G;h;$!d' file

At this point [[cmd-awk|awk]] or Python is usually easier to read.

Troubleshooting

  • sed: -i may not be used with stdin: -i requires a file argument, not a pipe.
  • sed: 1: "...": invalid command code on macOS: you are running BSD sed. Install brew install gnu-sed and call gsed.
  • unterminated 's' command: a closing / is missing, or a special character in the pattern is not escaped.
  • Substitution does nothing, but grep finds a match: without -E, sed uses BRE, so (foo|bar) is a literal string, not a group.
  • In-place editing breaks a symlink: GNU sed renames the file by default, severing the link. Use --follow-symlinks.
  • Encoding breaks: sed works byte by byte. For UTF-8 with multi-byte character classes like [[:alpha:]], you need the correct locale (LC_ALL=ru_RU.UTF-8).

Alternatives

  • awk: when you need field processing, counters, or aggregation.
  • perl -pe / perl -i: PCRE, lookahead, and more predictable cross-platform behavior.
  • sd (Rust): a modern CLI tool with PCRE by default and a cleaner syntax.

§ команды

bash
sed -i.bak 's/foo/bar/g' config.yml

Replace all occurrences of foo with bar in place; backup saved to config.yml.bak.

bash
sed -n '/^ERROR/,/^$/p' app.log

Print blocks from an ERROR line to the next blank line. Targeted context grep.

bash
sed '/^#/d;/^$/d' /etc/nginx/nginx.conf

Strip comment lines and blank lines. Shows the config as it is actually applied.

bash
sed -E 's|http://([^/]+)/.*|\1|' urls.txt | sort -u

Extract the hostname from each URL using a capture group and ERE.

bash
find . -name '*.py' -exec sed -i 's/print /print(/g' {} +

Bulk substitution across a directory tree. Useful for version migration.

bash
sed '5,10!d' file.txt

Keep only lines 5-10. `!d` means: do not delete the range, delete everything else.

bash
echo 'a b c' | sed -E 's/(\w+) (\w+) (\w+)/\3 \2 \1/'

Reverse the order of three words. Demonstrates capture groups.

§ см. также

  • cmd-grepgrep: search lines by pattern`grep` searches stdin or files for lines matching a regex. Key modes: `-E` (ERE), `-P` (PCRE), `-F` (fixed string), `-r` (recursive tree walk).
  • cmd-awkawk: field-oriented processing of structured textawk splits a line into fields by FS (default is whitespace) and applies pattern { action }. `$1..$NF`, `NR` (a counter), BEGIN/END for a prologue and totals. It covers 80% of "process the columns" tasks without Python.
  • bash-scriptingbash scripts: basics and idiomsA bash script is a text file with shebang `#!/usr/bin/env bash` and `chmod +x`. Start every script with `set -euo pipefail` and run `shellcheck` to catch errors early.
  • xargs-and-find-execxargs and find -exec: bulk operationsTwo ways to apply a command to a set of files: `find ... -exec cmd {} +` (inside find) and `... | xargs cmd` (via pipe). For safety with spaces and special characters, use `find -print0 | xargs -0`.
  • cmd-findfind: search files by predicates`find` walks a directory tree and applies predicates (name, type, time, size, permissions). Actions: `-print` (default), `-delete`, `-exec`, `| xargs`.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies