The utility Sed, stream editor, can be found on almost all unix-based systems. Sed takes a steam of text and, as the name suggests, edits it according to some instructions you have given it. It is a very flexible tool and can be very useful when using the commandline or in a shell script.

As a classic Hello World example do

sed 's/.*/Hello World/g'

Then press enter a few times and see sed replace the lines with Hello World.

This article contains some (fairly artificial) examples in order to demonstrate the features of sed. There are far more features than are in the scope of this article; I suggest checking out the man page if you are curious for more.

Uses

There is nothing that sed can do that is unique. Other tools such as grep awk and perl can be used for similar things to name just a few. Sed provides a style of working that some people like the most.

A simple use for sed is the situation when you are running some software that produces a lot of output but you only care about certain messages and do not want to miss them amidst the output you don't care about, maybe these messages appear in blocks starting with a line WARNING: and ending with an empty line. In this case you can do

./some_software | sed -n '/WARNING:/, /^$/p'

The -n option tells sed not to print the output of ./some_software unless explicitly told to do so by the print instruction, written p, this comes at the end of our sed command. Before it there are two regular expressions in forward slashes separated by a comma. This tells sed that you want to print in the range of lines between any that match those two regular expressions.

Another useful command that can go in place of the print command is the delete line command which is written d. Now when your boss is watching you can show him that it runs without any warnings by removing all the lines containing the string WARNING with

./some_software | sed '/WARNING/d'

Notice that the -n option is not there because we want sed to print all the text that is being output by ./some_software unless it matches WARNING, in which case delete that line from the stream.

Yet another usecase is taking the output of one command and changing parts of it; This is called a substitution and is done with the s/. For example, maybe you are having problems with a piece of software. You want to ask for help on an online forum but need to be careful not to post personal information which is included in the command output. Maybe it gives away that your name is Joe Bloggs so you do

./some_software | sed 's/Joe Blogs/<Name Redacted>/g'

For a more involved example, imagine you want to get the IP address of the wlan0 interface on your machine and put it in a variable in a shell script. ifconfig might ouput something that looks like:

wlan0     Link encap:Ethernet  HWaddr 08:11:96:05:6b:6c  
          inet addr:192.168.1.122  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::a11:96ff:fe05:6b6c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:67062 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18075 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:21572026 (20.5 MiB)  TX bytes:3448315 (3.2 MiB)

We want to extract the address 192.168.1.122. By eyeballing it we can see that we want the line after it says wlan0, then we want to match the regex inet addr:[^ ]* and we want to print that. You could use the following line

wlan0ip=$(ifconfig | sed -n '/wlan0/{n; s/.*inet addr:\([^ ]*\).*/\1/p; q}')

Notice that in this command after the /wlan0/ to match there is a curley brace. This is a block like in other programming languages because all the commands between the braces will be executed when there is a matching line. Commands are separated by semicolons. The n command simply tells sed to look at the next line. The next bit is a little fiddly. We only want to output the IP address, not the whole line so instead of doing a normal print p I used the s/.*(<some regex>).*/\1/p trick. This is a fairy standard trick which replaces the entire line with just the match before printing it in order to only print what you want. Finally the q tells sed to quit because you have found what you want and do not need to process the remainder of the output.

Limitations

Sed is bad when you need a line that comes before a matching line. Sed never goes backwards so by the time it finds the matching line it has already thrown away.

It is not a problem with SED to print a previous line if the current line match something. You just copy the pattern space (current line) into the Hold Space area. If there is a match, you can copy the Hold Space back into the pattern space.

eg.

sed -n ' /MATCH/ { g ; p } ; h '

Comment by MartinMSPedersen Sat Apr 30 17:12:44 2016