sed: the stream editor
sed edits text as it flows past, without opening an editor. Its most famous command is s, substitute: s/old/new/.
cat app.conf
sed 's/8080/9090/' app.confIn the terminal
student@vulntech:~$ cat app.conf # Treasure tracker settings host=localhost port=8080 debug=true # who to call admin=captain@old-ship.example backup=mate@old-ship.example student@vulntech:~$ sed 's/8080/9090/' app.conf # Treasure tracker settings host=localhost port=9090 debug=true # who to call admin=captain@old-ship.example backup=mate@old-ship.example
By itself, sed only prints the changed text: the file is untouched. Check with grep:
grep port app.confIn the terminal
student@vulntech:~$ grep port app.conf port=8080
Every match: the g flag
s replaces only the first match on each line. Add g (global) to replace them all:
echo "red red red" | sed 's/red/blue/'
echo "red red red" | sed 's/red/blue/g'In the terminal
student@vulntech:~$ echo "red red red" | sed 's/red/blue/' blue red red student@vulntech:~$ echo "red red red" | sed 's/red/blue/g' blue blue blue
Changing the file: -i
-i (in place) writes the changes back into the file. -i.bak keeps a copy of the original first:
sed -i.bak 's/debug=true/debug=false/' app.conf
grep debug app.conf app.conf.bakIn the terminal
student@vulntech:~$ sed -i.bak 's/debug=true/debug=false/' app.conf student@vulntech:~$ grep debug app.conf app.conf.bak app.conf:debug=false app.conf.bak:debug=true
Common mistake:
sed -ihas no undo. Run the command without-ifirst, check the output, then add-i.
Deleting and printing lines
| Command | What it does |
|---|---|
sed '/^#/d' | Delete the lines that match (here: comments) |
sed '/^$/d' | Delete empty lines |
sed -n '2,4p' | Print only lines 2 to 4 (-n = don't print the rest) |
sed '3d' | Delete line 3 |
sed '/^#/d' app.conf
sed -n '2,4p' app.confIn the terminal
student@vulntech:~$ sed '/^#/d' app.conf host=localhost port=8080 debug=true admin=captain@old-ship.example backup=mate@old-ship.example student@vulntech:~$ sed -n '2,4p' app.conf host=localhost port=8080 debug=true
Paths: pick another separator
When the text has slashes in it, use another character after s, such as |, so you don't have to escape every /:
echo /var/www/site | sed 's|/var/www|/srv/www|'In the terminal
student@vulntech:~$ echo /var/www/site | sed 's|/var/www|/srv/www|' /srv/www/site
Remember:
sed 's/old/new/g' fileshows the result,-ichanges the file,/pattern/ddeletes lines and-n '2,4p'prints lines 2 to 4.