Sed is a non-interactive line-based text editor. It can perform an edition in either file or STDIN
and print it in STDOUT
, which can later be redirected to a file it needed.
-e Editing instructions follows
-f File name of script follows
-n Supress automatic output of lines
-i Extension - Edit files in-place, saving backups with the specified extension.
If a zero-length extension is given, no backup will be saved.
$ sed -e "some instructions" my-file
$ sed -f my-script my-file
To delete a line:
$ # deletes a line - this returns nothing because all lines were deleted!
$ sed -e "d" some-file
$ # `-e' is the default option
$ sed "d" some-file
$ # you can delete lines matching a regular expression
$ sed "/^[A-Z]/d" some-file
$ # the above deletes all lines which start with
$ # an uppercase letter from A to Z
$ # you can also specify a range using `,'
$ sed "/^Start/,/^End/d" my-file
$ # the command above will delete from the line
$ # matching /^Start/ all the way until the line
$ # matching /^End/. If it never finds it, it
$ # deletes til the end of the file
$ # use `!' to reverse the match, meaning delete
$ # everything BUT this regex
$ sed "/[^A-Z]/!d
To substitute a line:
$ cat my-file
I have a dog dog
$ sed "s/dog/cat/" my-file
I have a cat dog
$ sed "s/dog/cat/g" my-file
I have a cat cat
$ # you can use any delimiter
$ sed "s!dog!cat!g" my-file
When substituting a line, you have a few metacharacters:
& - Replaced by the string matched by the regular expression.
\n - Matches the n th substring (n is a single digit) previously specified in the pattern using “\(” and “\)”.
\ - Used to escape the ampersand (&), the backslash (\)
Metacharacters can be used like this:
$ echo "dog" | sed "s/dog/big &/"
big dog
To supress the automatic printing, and do it explicitly instead, use -n
:
$ # print only if it matches /cat/
$ sed -n "/cat/p" my-file
To exclude a line use !
:
$ # replace all `--` with `—`
$ sed '/---/!s/--/—/g' my-file
$ # because we don't want to alter lines which
$ # might be an horizontal separator (eg: '---------')
$ # let's ignore all lines matching /---/
n
A number (1 to 512) indicating that a replacement should be made for only
the n th occurrence of the patter n.
g
Make changes globally on all occurrences in the pattern space. Normally only
the first occurrence is replaced.
p
Print the contents of the pattern space.
w file
Write the contents of the pattern space to file.
Flags can be combined, like gp
.
You can chain commands with ;
:
$ sed "/^[A-Z]/d; s/dog/cat/g" my-file
You can group commands by using {}
:
$ cat my-script
/^Start/,/^End/{
/^$/d
}
$ sed -f my-script some-file
In that expression, sed
will group all the lines inside the given range, and then delete the empty lines (lines matching /^$/
) only inside that group.
You can use sed
as a more powerful grep
. For example, you can fetch a range:
$ cat foo
START
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque venenatis
dolor ac tempus accumsan. Vivamus porta et arcu vitae vestibulum. Aenean
END
lacinia justo ac euismod feugiat. Nulla sit amet pharetra nulla, eget dignissim
est. In venenatis feugiat nisl. Sed vel venenatis metus. Ut quis quam purus.
START
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
END
inceptos himenaeos. Fusce condimentum egestas velit, id ultricies nunc
vestibulum at.
$ sed -n "/START/,/END/p" foo
START
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque venenatis
dolor ac tempus accumsan. Vivamus porta et arcu vitae vestibulum. Aenean
END
START
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
END
And you can modify the contents before returning them:
$ cat overview-md
sed -n '
s/^###/ /p
s/^##/ /p
s/^#//p
' $*
$ cat markdown-file
# Section 1.
[...]
## Section 1.1
[...]
### Section 1.1.1
[...]
## Section 1.2
[...]
# Section 2
[...]
$ overview-md markdown-file
Section 1.
Section 1.1
Section 1.1.1
Section 1.2
Section 2
$ # for macOS
$ find -name "*.rb" | xargs sed -i "" "s/FactoryGirl/FactoryBot/g"
$ # for Linux
$ find -name "*.rb" | xargs sed -i "s/FactoryGirl/FactoryBot/g"