Stream Editor - Loops



Like other programming languages, SED too provides a looping and branching facility to control the flow of execution. In this chapter, we are going to explore more about how to use loops and branches in SED.

A loop in SED works similar to a goto statement. SED can jump to the line marked by the label and continue executing the remaining commands. In SED, we can define a label as follows:

:label 
:start 
:end 
:up

In the above example, a name after colon(:) implies the label name.

To jump to a specific label, we can use the b command followed by the label name. If the label name is omitted, then the SED jumps to the end of the SED file.

Let us write a simple SED script to understand the loops and branches. In our books.txt file, there are several entries of book titles and their authors. The following example combines a book title and its author name in one line separated by a comma. Then it searches for the pattern "Paulo". If the pattern matches, it prints a hyphen(-) in front of the line, otherwise it jumps to the Print label which prints the line.

[jerry]$ sed -n ' 
h;n;H;x 
s/\n/, / 
/Paulo/!b Print 
s/^/- / 
:Print 
p' books.txt

On executing the above code, you get the following result:

A Storm of Swords, George R. R. Martin 
The Two Towers, J. R. R. Tolkien 
- The Alchemist, Paulo Coelho 
The Fellowship of the Ring, J. R. R. Tolkien 
- The Pilgrimage, Paulo Coelho
A Game of Thrones, George R. R. Martin 

At first glance, the above script may look cryptic. Let us demystify this.

  • The first two commands are self-explanatory h;n;H;x and s/\n/, / combine the book title and its author separated by a comma(,).

  • The third command jumps to the label Print only when the pattern does not match, otherwise substitution is performed by the fourth command.

  • :Print is just a label name and as you already know, p is the print command.

To improve readability, each SED command is placed on a separate line. However, one can choose to place all the commands in one line as follows:

[jerry]$ sed -n 'h;n;H;x;s/\n/, /;/Paulo/!b Print; s/^/- /; :Print;p' books.txt 

On executing the above code, you get the following result:

A Storm of Swords, George R. R. Martin 
The Two Towers, J. R. R. Tolkien 
- The Alchemist, Paulo Coelho 
The Fellowship of the Ring, J. R. R. Tolkien 
- The Pilgrimage, Paulo Coelho 
A Game of Thrones, George R. R. Martin
Advertisements