Skip to content
AgileLogics
6 min read

Editing Text with sed

Prerequisites: Searching text with grep

sed (stream editor) transforms text line by line. Its most common job is find and replace.

Substitution

echo "I love cats. cats are great." | sed 's/cats/dogs/'
echo "I love cats. cats are great." | sed 's/cats/dogs/g'
echo "Hello World" | sed 's/world/there/I'
I love dogs. cats are great.
I love dogs. dogs are great.
Hello there

s/old/new/ replaces the first match on each line; the g flag replaces all matches; I ignores case (GNU sed).

Editing files

cat > config.ini <<'EOF'
host=localhost
port=8080
debug=true
EOF

sed 's/port=8080/port=9090/' config.ini
echo "--- file unchanged:"
cat config.ini
sed -i.bak 's/debug=true/debug=false/' config.ini
echo "--- after sed -i:"
cat config.ini
ls config.ini*
host=localhost
port=9090
debug=true
--- file unchanged:
host=localhost
port=8080
debug=true
--- after sed -i:
host=localhost
port=8080
debug=false
config.ini
config.ini.bak
  • By default, sed prints the result and leaves the file alone.
  • -i edits the file in place. -i.bak keeps a backup first — a good habit. (On macOS's BSD sed, -i requires an argument: -i '' for no backup.)

Selecting lines

printf 'line %s\n' 1 2 3 4 5 > nums.txt

sed -n '2,4p' nums.txt
echo "---"
sed '1d' nums.txt
echo "---"
sed '/3/d' nums.txt
line 2
line 3
line 4
---
line 2
line 3
line 4
line 5
---
line 1
line 2
line 4
line 5
  • -n '2,4p' prints only lines 2 to 4.
  • 1d deletes line 1 (handy for skipping a CSV header).
  • /pattern/d deletes lines matching a pattern.

Capture groups

echo "2025-04-22" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/'
echo "Ada Lovelace" | sed -E 's/(\w+) (\w+)/\2, \1/'
22/04/2025
Lovelace, Ada

-E enables extended regex; ( ) captures parts, and \1, \2, \3 insert them in the replacement.

Common mistakes

  • Slashes in the text: replacing paths with s/\/usr\/local/... gets unreadable. Use a different delimiter: s#/usr/local#/opt#.
  • Running sed -i without testing the expression first. Run it without -i, check the output, then add -i.