Last updated:
sed
is a stream editor that reads and manipulates text using functions you specify in your command. sed
understands regular expressions, which makes it a powerful toy.
sed
can be a handy tool if you want to print specific lines in a file. For instance, you can use sed
to print lines 21 to 32 of a wp-config.php file:
$ sed -n 21,32p wp-config.php // ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define( 'DB_NAME', 'example_db' ); /** MySQL database username */ define( 'DB_USER', 'example_user' ); /** MySQL database password */ define( 'DB_PASSWORD', '?43 Rft>N>)8V@"D7.<I' ); /** MySQL hostname */ define( 'DB_HOST', 'localhost' );
The -n
option prevents sed
from printing every line in the file and 21,32p
prints lines 21 to 32.
Our aim with the above command is to get the database connection information. We therefore really just want the lines that start with “define”. To get that information we could pipe the output to grep
. The below command prints all lines that start with (^
) the string “define”:
$ sed -n 21,32p wp-config.php | grep ^define wp-config.php define( 'DB_NAME', 'example_db' ); define( 'DB_USER', 'example_user' ); define( 'DB_PASSWORD', '?43 Rft>N>)8V@"D7.<I' ); define( 'DB_HOST', 'localhost' );
You can print the same lines using only sed
with multiple -e
options. Here, we are printing lines 23, 26, 29 and 32:
$ sed -n -e 23p -e 26p -e 29p -e 32p wp-config.php define( 'DB_NAME', 'example_db' ); define( 'DB_USER', 'example_user' ); define( 'DB_PASSWORD', '?43 Rft>N>)8V@"D7.<I' ); define( 'DB_HOST', 'localhost' );
It is of course also possible to just use grep
. However, if you just look for lines that start with “define” (and perhaps include the string “DB_”) then you get a few extra lines:
$ grep ^define.*DB_ wp-config.php define( 'DB_NAME', 'example_db' ); define( 'DB_USER', 'example_user' ); define( 'DB_PASSWORD', '?43 Rft>N>)8V@"D7.<I' ); define( 'DB_HOST', 'localhost' ); define( 'DB_CHARSET', 'utf8' ); define( 'DB_COLLATE', '' );
sed
is commonly used to replace text. You may develop websites on your localhost, where the path to files is different than the path on the live server. For instance, on your localhost your document root perhaps includes the website’s domain name:
$ cat /var/www/html/example.net/_incs/header.html <header id="header"> <h1 id="mast"><a href="/example.net/">Examples Rock!</a></h1> </header>
Here, the document root is /example.net/. On the live server the document root is likely to be /. Before uploading files to the live server all instances of /example.net/ therefore need to be changed to /. sed
can do this for you. The basic command for substituting text is as follows:
sed 's/old_text/new_text/g' file_name
The s
tells sed
that we want to substitute text and the g
at the end of the command is short for “global”. With the global option sed
replaces all instances of old_text
with new_text
on a line. Without the option only the first instance on a line is replaced.
To replace the string /example.net/ with / we can use the following command:
$ sed 's/\/example.net\//\//g' /var/www/html/example.net/_incs/header.html <header id="header"> <h1 id="mast"><a href="/">Examples Rock!</a></h1> </header>
Note that we escaped the forward strokes (/
) in the strings with backward strokes (\
). That is necessary, as sed
uses forward strokes to delimit the different parts of the command. All the escaped strokes make the command difficult to read. Luckily, you don’t have to use strokes as the delimiter. You can specify any other character, such as the pipe symbol (|
). As you can see, that makes the command much more readable:
$ sed 's|/example.net/|/|g' /var/www/html/example.net/_incs/header.html <header id="header"> <h1 id="mast"><a href="/">Examples Rock!</a></h1> </header>
So far, our changes have not been saved. We asked sed
to replace a string and the editor dived into the file we specified. It looked at every line in the file, made the substitution we wanted, and printed the lines to the screen. The original file hasn’t changed though:
$ cat /var/www/html/example.net/_incs/header.html <header id="header"> <h1 id="mast"><a href="/example.net/">Examples Rock!</a></h1> </header>
To edit files ‘in place’ you need to add the -i
option:
$ sed -i 's|/example.net/|/|g' /var/www/html/example.net/_incs/header.html $ cat /var/www/html/example.net/_incs/header.html <header id="header"> <h1 id="mast"><a href="/">Examples Rock!</a></h1> </header>
If you give the -i
option a suffix you get two versions of the file: before the original file is overwritten sed
saves a copy of the original file using the suffix you specified:
$ sed -i.BAK 's|/example.net/|/|g' /var/www/html/example.net/_incs/header.html $ cat /var/www/html/example.net/_incs/header.html <header id="header"> <h1 id="mast"><a href="/">Examples Rock!</a></h1> </header> $ cat /var/www/html/example.net/_incs/header.html.BAK <header id="header"> <h1 id="mast"><a href="/example.net/">Examples Rock!</a></h1> </header>
That’s all very dandy, you might say, but wouldn’t it be easier to just open the file in a normal editor and do a search and replace? Which is true if you need to replace a string in just one or two files. But what if you need to replace the same string in dozens or hundreds of files?
Combining sed
with other utilities will save the day. To continue with our example, if you want to replace the string /example.net/ with just a single stroke throughout the /var/www/html/example/ directory then you can combine sed
with find
and xargs
:
$ find /var/www/html/example/ -name "*.html" -print0 \ | xargs -0 sed -i 's|/example.net/|/|g'
This commands first finds all files containing the string .html. The output of the find
command is then piped to xargs
which executes our sed
command. The -print0
and -0
options are used to deal with file names that contain spaces. Of course, HTML files names shouldn’t contain spaces, but it is always better to be safe than sorry.
This article has really just scratched the surface of what sed
can do. It is an incredibly flexible and powerful tool. If you are going spend lots of time working with text files on the command line then it is worth learning more about sed
. We quite like Bruce Barnett’s introduction to sed and Tutorial Point’s sed guide.