When working with text files on Linux, a few tools show up again and again:

  • grep for filtering content
  • sed for editing text streams
  • awk
  • regular expressions

Among them, sed is one of the most useful for direct text processing. It reads input line by line, checks whether each line matches a given condition, and then performs the requested action only on matching lines. If a line does not match, it is skipped.

sed is a powerful non-interactive stream editor in Linux. It can be used to search, add, delete, modify, and extract text. It supports operations by line number, by field, and by regular-expression matching, which makes it especially convenient when handling large files.

How sed works

sed is a line editor. It reads one line into memory, processes it there, and then sends the result to the screen. This temporary memory area is the pattern space.

By default, sed does not modify the original file. It only processes the data in pattern space and prints the result after processing.

Regular-expression basics used with sed

Before using sed well, it helps to know the common regex forms it relies on.

Metacharacters for matching a single character

  • .
  • [abc]
  • [a-z]
  • [A-Z]
  • [0-9]
  • [a-zA-Z0-9]
  • [^a-z]
  • [[:alpha:]]
  • [[:upper:]]
  • [[:lower:]]
  • [[:digit:]]

Matching by position

  • ^str — starts with str
  • str$ — ends with str
  • ^$ — empty line

Matching by occurrence count

  • *
  • \?
  • \+
  • \{3\}
  • \{2,5\}
  • \{2,\}

Basic sed syntax

# sed [option] scripts file1 file2…
# sed [option] ‘AddressCommand’ file1 file …

Here:

  • Address specifies which lines should be processed
  • Command is the operation to run

Common options

  • -n — do not print pattern-space content automatically
  • -i — edit the original file in place
  • -e — execute multiple commands
  • -f — read multiple AddressCommand entries from a file, one per line
  • -r — use extended regular expressions

Example of multiple commands:

[root0shell ~]+ sed -e ‘/^#/d’ -e ‘/^5/d’ /etc/fstab

Ways to specify an address

1. Line range

  • 1, 100
  • 1,$

2. Single line number

  • 3

3. Start line with offset

  • 5,+2
  • /root/,+2

4. Regular-expression match

  • /root/
  • /bash$/

5. Range between two regex matches

  • /正则表达式1/, /正则表达式2/

This means: start at the first line matched by the first regex and continue through the first line matched by the second regex, including everything in between.

Common sed commands

d — delete

Delete the first four lines:

<table> <thead> <tr> <th>1</th> <th>[root@wei init.d]# sed '1,4d' nginx.sh</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

Delete the last line:

<table> <thead> <tr> <th>1</th> <th>[root@wei init.d]# sed '$d' nginx.sh</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

Delete lines beginning with #:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed '/^#/d' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

Delete lines beginning with /:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed '/^\//d' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

Delete lines containing digits:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed '/[0-9]/d' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

p — print matching lines

Show lines that start with /:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed -n '/^\//p' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

a \string — append text after a matching line

Append # hello word after lines beginning with /:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed '/^\//a\# hello word' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

Append # hello word and # hello linux after lines beginning with /:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed '/^\//a\# hello word' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

i \string — insert text before a matching line

Insert # hello linux before the first line of the file:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed '1i \# hello linux' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

c \string — replace selected content

Replace the last line of the file with end of file:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed '$c\end of file' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

= — print line numbers

Show the line number of the last line in /etc/passwd:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed -n '$=' /etc/passwd</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

r file_name — read a file and insert its contents after a matching line

Append the contents of /etc/issue after line 2 of /etc/fstab:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed '2r /etc/issue' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

w file_name — write matching content to another file

Save lines beginning with # into /1.txt:

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed '/^#/w /root/1.txt' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

Search and replace with sed

By default, sed replaces only the first match found in each line.

s /old/new/[modifier]

Where:

  • old — the regular expression to match
  • new — the replacement text

Common modifiers:

  • g — replace all matches in a line
  • i — ignore case

Replace UUID with uuid

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed 's/UUID/uuid/' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

Replace a leading / at the start of a line with #

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed 's/^\//#/' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table> <table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed 's|/|#|g' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

Replace every / in each line with @

<table> <thead> <tr> <th>1</th> <th>[root@wei ~]# sed 's/\//@/g' /etc/fstab</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> </tbody> </table>

sed is often introduced as a simple substitution tool, but it is far more than that. Once you combine addresses, commands, and regular expressions, it becomes a compact and efficient way to edit text directly from the shell, especially when dealing with large files or script-based automation.