One of the most important command line utility in Linux is
sed which is a stream editor.
A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline).
Essentially what it can do is it allows you to search for String of text or specific pattern and then replace it pattern with whatever you tell sed to replace with, so it is really kind of search and replace function.
sed 's/find/replace/' <oldfile >newfile
So we are telling sed that go search for the word
find then replace it with the word
replace and what it does is it searches every lines for its first instance of the word
find. So it not gonna replace every instances of
find, only the first time it appears on each line from
oldfile and then writes it to
Sometimes you want to replace every
oldfile you just need to add global substitution
g for every instances
sed 's/find/replace/g' <oldfile >newfile
But What if you just want to take a file, change it then write to that same file, you could use
It will replace all occurrences of a string in a file, overwriting the file (i.e. in-place):
sed -i 's/find/replace/g' filename
You are not often doing this as far taking input from a file and then taking the output and write to new file. Probably most of the time, you take the output from other shell command and pipe it to
sed command. For example:
echo "Thank Do Hoang" | sed 's/Ho/W/' Thank Do Wang
Other basic usage:
- To replace only on lines matching the line pattern:
sed '/line_pattern/s/find/replace/' filename
- Delete lines matching the line pattern:
sed '/line_pattern/d' filename
- Print the first 11 lines of a file:
sed 11q filename
- Apply multiple find-replace expressions to a file:
sed -e 's/find/replace/' -e 's/find/replace/' filename
- Replace separator
/by any other character not used in the find or replace patterns, e.g.
sed 's#find#replace#' filename
What if I want to search for multiple pattern?
cat /etc/shells | sed -e 's/usr/u/g' -e 's/bin/b/g'
Sed is not picky about the symbol that you use for the separator in the
command, if you dont want to use the /, you can use pretty much any others kind of special symbol that you can think of as long as it is not part of the search pattern.
cat /etc/shells | sed -e 's|usr|u|g' -e 's#bin#b#g'
You can also print specific line that match the search pattern ( kind of
cat /etc/shells | sed -n '/usr/p'
The cool trick about
sed is to go and delete extra spaces at the end of the line, for example
sed -i 's/ *$//' test.sh
It will search for every lines that has spaces at the end of it and replace it with nothing (basically deleting them).
How about tabs?
sed -i 's/[[:space:]]*$//' test.sh
cat test.sh | sed '/^$/d'
^ is the begining of the line then the
$ symbol is the end of the line ( find every pattern that match the begining of the line, and the end of the line and there is nothing between it - so that means that line is empty ).
You can also replace all the lowercase characters with uppercase characters for fun 🙃
sed 's/[a-z]\/U&/g' test.sh // uppercase sed 's/[a-z]\/L&/g' test.sh // lowercase
C'est tout, merci kn 🙃