Sed Branches
Stream Editor - Conditional Branching
Section titled “Stream Editor - Conditional Branching”SED scripts can make decisions and jump to different parts of the script using branch commands. This allows for more complex text processing logic, similar to goto statements in other programming languages. The primary commands for branching are b, t, and T.
The b Command (Unconditional Branch)
Section titled “The b Command (Unconditional Branch)”The b command unconditionally jumps to a label. If no label is provided, it branches to the end of the script, effectively skipping any subsequent commands for the current cycle.
The t Command (Conditional Branch on Success)
Section titled “The t Command (Conditional Branch on Success)”The t label command jumps to the specified label only if a s/// (substitute) command has made a successful substitution since the last input line was read or the last t or T command was executed. If no label is provided, it branches to the end of the script. This is useful for performing actions only when a change has occurred.
Let’s see a simple example. Suppose we want to mark lines containing “Martin” by prepending “AUTHOR_UPDATE: ” but only if we successfully replace “Martin” with “M.A.R.T.I.N”. We’ll use our standard books.txt file:
File: `books.txt`1) A Storm of Swords, George R. R. Martin, 12162) The Two Towers, J. R. R. Tolkien, 3523) The Alchemist, Paulo Coelho, 1974) The Fellowship of the Ring, J. R. R. Tolkien, 4325) The Pilgrimage, Paulo Coelho, 2886) A Game of Thrones, George R. R. Martin, 864[jerry]$ sed '/Martin/ { s/Martin/M.A.R.T.I.N/ t was_substituted}b # Skip if no substitution or not Martin:was_substituteds/^/AUTHOR_UPDATE: /' books.txtExecuting this command yields:
AUTHOR_UPDATE: 1) A Storm of Swords, George R. R. M.A.R.T.I.N, 12162) The Two Towers, J. R. R. Tolkien, 3523) The Alchemist, Paulo Coelho, 1974) The Fellowship of the Ring, J. R. R. Tolkien, 4325) The Pilgrimage, Paulo Coelho, 288AUTHOR_UPDATE: 6) A Game of Thrones, George R. R. M.A.R.T.I.N, 864Here, if s/Martin/M.A.R.T.I.N/ is successful, t was_substituted jumps to the label :was_substituted, and s/^/AUTHOR_UPDATE: / is executed. Otherwise, the t command does nothing, and b (unconditional branch to end of script for this line) would be hit, or if not present, execution would continue to the label command (which does nothing by itself) and then the prefix substitution, which is not what we’d want for non-Martin lines. The current logic ensures only substituted lines get the prefix.
Iterative Example with t (Looping)
Section titled “Iterative Example with t (Looping)”The t command is powerful for creating loops. Let’s consider an example where we want to prepend up to four hyphens to lines containing “Paulo”. This example involves joining lines first, so we’ll use a slightly different input file, books_split.txt, where titles and authors are on separate lines:
File: `books_split.txt`A Storm of SwordsGeorge R. R. MartinThe Two TowersJ. R. R. TolkienThe AlchemistPaulo CoelhoThe Fellowship of the RingJ. R. R. TolkienThe PilgrimagePaulo CoelhoA Game of ThronesGeorge R. R. MartinThe command uses h; n; H; x to join pairs of lines, then s/\n/, / to replace the embedded newline with a comma and space. After that, it enters a loop for lines containing “Paulo”.
[jerry]$ sed -n 'h;N;H;xs/\n/, /:Loop/Paulo/s/^/-/;/----/!t Loopp' books_split.txtWhen the above code is executed, it produces the following result:
A Storm of Swords, George R. R. MartinThe Two Towers, J. R. R. Tolkien----The Alchemist, Paulo CoelhoThe Fellowship of the Ring, J. R. R. Tolkien----The Pilgrimage, Paulo CoelhoA Game of Thrones, George R. R. MartinLet’s break down the looping part:
h;N;H;x: These commands work together.hcopies the first line (e.g., title) to hold space.Nappends the next line (e.g., author) to pattern space (this is slightly different from the originalh;n;H;x;buth;N;H;xis also a common idiom for joining two lines, effectivelyNfollowed byG; s/\n//when hold space has the first line). A simplerN ; s/\n/, /would often suffice for joining two lines if printing immediately. The original sequenceh;n;H;xmeans: Line 1 to hold. Line 2 to pattern. Append Line 2 to hold (Hold: L1\nL2). Swap pattern and hold (Pattern: L1\nL2).s/\n/, /: Replaces the newline (now in pattern space) with a comma and space.:Loop: Defines a label namedLoop./Paulo/s/^/-/: Checks if the (joined) line contains "Paulo". If yes, it prepends a hyphen (-) to the beginning of the line. Thiss///command is the one that determines ift` will branch./----/!t Loop: This is the conditional branch.!t Loopmeans: if the pattern space does not match/----/(i.e., does not start with four hyphens), and the precedings///command (/Paulo/s/^/-/) was successful, then jump back to theLooplabel. If thes///was not successful (e.g. “Paulo” not in line),twill not branch.p: Prints the (potentially modified) line from the pattern space.-nsuppresses default output, sopis needed here. This process repeats, adding one hyphen at a time to lines with “Paulo”, until four hyphens are prepended or “Paulo” is not found.
To improve readability, SED commands can be written on separate lines in a script file or using -e for each command. For a one-liner, you can use semicolons (though newlines are often clearer as shown above):
[jerry]$ sed -n 'h;N;H;x; s/\n/, /; :Loop; /Paulo/s/^/-/; /----/!t Loop; p' books_split.txtThe output is the same:
A Storm of Swords, George R. R. MartinThe Two Towers, J. R. R. Tolkien----The Alchemist, Paulo CoelhoThe Fellowship of the Ring, J. R. R. Tolkien----The Pilgrimage, Paulo CoelhoA Game of Thrones, George R. R. MartinThe T Command (Conditional Branch on Failure - GNU Extension)
Section titled “The T Command (Conditional Branch on Failure - GNU Extension)”The T label command is a GNU extension. It’s the opposite of t: it jumps to label only if the last s/// command failed to make a substitution. If no label is provided, it branches to the end of the script. This is useful for actions when a specific pattern wasn’t found and replaced.
Understanding branching unlocks advanced scripting capabilities in SED, allowing for sophisticated text transformations based on conditions within your data.