DEV Community

Franz Wong
Franz Wong

Posted on • Edited on

sed cookbook

Table of contents

Write the result to another file

Content of file_1 (before command is executed)

Hello World
Enter fullscreen mode Exit fullscreen mode

Command

sed 's/Hello/Goodbye/;w file_2' file_1
Enter fullscreen mode Exit fullscreen mode

Content of file_1 (after command is executed)

Hello World
Enter fullscreen mode Exit fullscreen mode

Content of file_2 (after command is executed)

Goodbye World
Enter fullscreen mode Exit fullscreen mode

Replace first occurrence on every

Input file

aa
bb bb
aa
bb
Enter fullscreen mode Exit fullscreen mode

Command

sed 's/bb/dd/' file
Enter fullscreen mode Exit fullscreen mode

Output

aa
dd bb
aa
dd
Enter fullscreen mode Exit fullscreen mode

Replace values of all occurrences

Input file

aa
bb bb
aa
bb
Enter fullscreen mode Exit fullscreen mode

Command

sed 's/bb/dd/g' file
Enter fullscreen mode Exit fullscreen mode

Output

aa
dd dd
cc
dd
Enter fullscreen mode Exit fullscreen mode

Replace value of first occurrence in the file

Input file

aa
bb bb
aa
bb
Enter fullscreen mode Exit fullscreen mode

Command

It only works on GNU sed.
See also: https://www.gnu.org/software/sed/manual/html_node/Range-Addresses.html

sed '0,/bb/{s/bb/dd/}' file
Enter fullscreen mode Exit fullscreen mode

Output

aa
dd bb
cc
bb
Enter fullscreen mode Exit fullscreen mode

Replace all occurrences on n-th line

Input file

aa
bb bb
aa
bb
Enter fullscreen mode Exit fullscreen mode

Command

# replace all occurrences on 2nd line
sed '2s/bb/dd/g' file
Enter fullscreen mode Exit fullscreen mode

Output

aa
dd dd
aa
bb
Enter fullscreen mode Exit fullscreen mode

Replace all occurrences within a range of lines

Input file

aa1
aa2
aa3
aa4
aa5
Enter fullscreen mode Exit fullscreen mode

Command

# replace occurrences from 2nd line to 4th line
sed '2,4s/aa/dd/g' file
Enter fullscreen mode Exit fullscreen mode

Output

aa1
dd2
dd3
dd4
aa5
Enter fullscreen mode Exit fullscreen mode

Replace all occurrences on every line matching pattern

Input file

a 1
a 2
a 1 x
b 1
b 2
b 1 x
c 1
c 2
c 1 x
Enter fullscreen mode Exit fullscreen mode

Command

# replace "1" with "10" on all the lines containing "b"
sed '/b/s/1/10/g' file1
Enter fullscreen mode Exit fullscreen mode

Output

a 1
a 2
a 1 x
b 10
b 2
b 10 x
c 1
c 2
c 1 x
Enter fullscreen mode Exit fullscreen mode

Replace all occurrences on every line NOT matching pattern

Input file

a 1
a 2
a 1 x
b 1
b 2
b 1 x
c 1
c 2
c 1 x
Enter fullscreen mode Exit fullscreen mode

Command

# replace "1" with "10" on all the lines NOT containing "b"
sed '/b/!s/1/10/g' file
Enter fullscreen mode Exit fullscreen mode

Output

a 10
a 2
a 10 x
b 1
b 2
b 1 x
c 10
c 2
c 10 x
Enter fullscreen mode Exit fullscreen mode

Replace first occurrence after a pattern

Input file

server-alpha:
    host: '192.168.0.1'
    port: 9090

server-beta:
    host: '192.168.0.1'
    port: 9091

server-charlie:
    host: '192.168.0.1'
    port: 9092
Enter fullscreen mode Exit fullscreen mode

Problem

Change the host of server-beta to 192.168.0.2. Values of other hosts remain unchanged.

Command

sed -e '/server-beta/! b' \
    -e ':label1' \
    -e 's/192.168.0.1/192.168.0.2/' \
    -e 't label2' \
    -e 'n' \
    -e 'b label1' \
    -e ':label2' \
    -e 'n' \
    -e 'b label2' \
    file
Enter fullscreen mode Exit fullscreen mode

Output

server-alpha:
    host: '192.168.0.1'
    port: 9090

server-beta:
    host: '192.168.0.2'
    port: 9091

server-charlie:
    host: '192.168.0.1'
    port: 9092
Enter fullscreen mode Exit fullscreen mode

Explanation

It uses the sed branching commands b and t.

  • /server-beta/! b - if pattern space doesn't contain server-beta, it will jump to the end of script.

  • :label1 - declare a label with name label1

  • s/192.168.0.1/192.168.0.2/ - Replace 192.168.0.1 with 192.168.0.2

  • t label2 - if the previous replacement is done, jump to label2.

  • n - read next line from input and put to pattern space or exit if no more line from input

  • b label1 - jump to label1

  • :label2 - declare a label with name label2

  • n - read next line from input and put to pattern space or exit if no more line from input

  • b label2 - jump to label2

Pseudo code

input = readLineFromInput()
while (input != null) {
    patternSpace.append(input)

    if (patternSpace.contains("server-beta")) {
        while (true) { // label1
            if (patternSpace.replace("192.168.0.1", "192.168.0.2")) {
                break // jump to label2
            }
            /** start of n **/
            display(patternSpace)
            patternSpace.clear()
            input = readLineFromInput()
            if (input == null) {
                exit
            }
            patternSpace.append(line)
            /** end of n **/
        }

        while (true) { // label2
            /** start of n **/
            display(patternSpace)
            patternSpace.clear()
            input = readLineFromInput()
            if (input == null) {
                exit
            }
            patternSpace.append(line)
            /** end of n **/
        }
    }

    display(patternSpace)
    patternSpace.clear()
    input = readLineFromInput()
}
Enter fullscreen mode Exit fullscreen mode

Delete lines matching pattern

Input file

aa1
bb2
cc3
Enter fullscreen mode Exit fullscreen mode

Command

sed /bb/d file
Enter fullscreen mode Exit fullscreen mode

Output

aa1
cc3
Enter fullscreen mode Exit fullscreen mode

Delete n-th line

Input file

aa1
aa2
aa3
aa4
aa5
Enter fullscreen mode Exit fullscreen mode

Command

# delete 2nd line
sed 2d
Enter fullscreen mode Exit fullscreen mode

Output

aa1
aa3
aa4
aa5
Enter fullscreen mode Exit fullscreen mode

Insert before line

Input file

aa1
bb2
cc3
Enter fullscreen mode Exit fullscreen mode

Command

sed "/bb/i bb_before" file
Enter fullscreen mode Exit fullscreen mode

Output

aa1
bb_before
bb2
cc3
Enter fullscreen mode Exit fullscreen mode

Insert after line

Input file

aa1
bb2
cc3
Enter fullscreen mode Exit fullscreen mode

Command

sed "/bb/a bb_after" file
Enter fullscreen mode Exit fullscreen mode

Output

aa1
bb2
bb_after
cc3
Enter fullscreen mode Exit fullscreen mode

Use other delimiter

Input file

/aa/bb/cc/dd
Enter fullscreen mode Exit fullscreen mode

Problem

It is too clumsy to escape slash.

sed 's/bb/bb1\/bb2\/bb3/' file
Enter fullscreen mode Exit fullscreen mode

Command

It is clearer if # is used.

sed 's#bb#bb1/bb2/bb3#' file
Enter fullscreen mode Exit fullscreen mode

Output

/aa/bb1/bb2/bb3/cc/dd
Enter fullscreen mode Exit fullscreen mode

Actually any character can be used.

These are all valid and produce same output.

# , is used
sed 's,bb,bb1/bb2/bb3,' file

# $ is used
sed 's$bb$bb1/bb2/bb3$' file

# a is used
sed 'sabbabb1/bb2/bb3a' file
Enter fullscreen mode Exit fullscreen mode

But you can't use character which is inside the pattern.

# b is used
sed 'sbbbbbb1/bb2/bb3b' file
# sed: -e expression #1, char 5: unknown option to `s'

# 1 is used
sed 's1bb1bb1/bb2/bb31' file
# sed: -e expression #1, char 9: unknown option to `s'
Enter fullscreen mode Exit fullscreen mode

Top comments (0)