100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Branching and Loops in sed

Learn how sed uses labels, unconditional branches, and conditional branches to build loops and control flow inside its scripting language.

Advanced sedAdvanced10 min readJul 10, 2026
Analogies

Why sed Needs Branching

By default sed reads one line, runs every command in the script top to bottom, prints, and repeats. That linear flow cannot handle tasks that need repetition within a single line or that need to skip commands based on a condition. Branching commands — labels defined with a colon, the unconditional branch 'b', and the conditional branches 't' and 'T' — turn sed from a line filter into a tiny programming language with jumps and loops.

🏏

Cricket analogy: A default sed pass is like a batsman playing every ball the same defensive shot; branching is the captain signalling a field change mid-over so the bowler switches plans based on the situation.

Labels and the Unconditional Branch 'b'

A label is declared with a colon followed by a name, such as ':top', and it marks a target position in the script. The 'b' command jumps to a label; 'b top' means 'go to :top'. A bare 'b' with no label jumps to the end of the script, effectively skipping the remaining commands for the current line — a handy way to short-circuit further processing once you know the line is done.

🏏

Cricket analogy: A label is like a marked crease line and 'b label' is the batsman calling for a quick single back to that exact spot; a bare 'b' is simply blocking and ending the over early.

Conditional Branches 't' and 'T'

The 't' command branches only if an 's' substitution has succeeded since the last input line was read or since the last 't'/'T'. This makes it the natural engine for loops: perform a substitution, then 't' back to the label so the substitution runs again, until it no longer matches and the branch is not taken. The 'T' command is the GNU inverse — it branches only when no substitution has succeeded. Together they let you build 'repeat until nothing changes' logic.

🏏

Cricket analogy: 't' is a DRS-style rule: only if the last appeal (substitution) was successful do you loop back for another review, whereas 'T' reacts only when the appeal was turned down.

A Practical Loop Example

bash
# Collapse every run of multiple spaces into a single space,
# looping until no double-space remains on the line.
echo 'a     b    c' | sed ':top; s/  / /; t top'
# Output: a b c

# Add a comma as a thousands separator to a bare integer.
echo '1234567' | sed -E ':loop; s/([0-9])([0-9]{3})($|,)/\1,\2\3/; t loop'
# Output: 1,234,567

In GNU sed you can separate a label and its branch with semicolons on one line, as in ':top; s/ / /; t top'. Some older or POSIX seds require the label and each 'b'/'t' command to be on their own line or terminated by a newline, so multi-line scripts with -e are the portable form.

It is easy to write an infinite loop. If the substitution inside a 't' loop always matches — for example 's/x/xx/' which keeps re-matching its own output — sed will spin forever. Always make sure each iteration moves toward a state where the pattern no longer matches.

  • Labels are declared with ':name' and mark jump targets in the script.
  • 'b' branches unconditionally; 'b label' jumps to the label, a bare 'b' skips to the end of the script.
  • 't' branches only if a substitution succeeded since the last line or last t/T — the basis of loops.
  • 'T' (GNU) is the inverse of 't', branching only when no substitution succeeded.
  • A typical loop is ':top; s/.../.../; t top' — substitute, then branch back until no match remains.
  • Ensure every iteration reduces matches, or the loop runs forever.
  • Semicolon-separated labels are a GNU convenience; POSIX sed often needs newline-separated commands.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#SedStreamEditorStudyNotes#BranchingAndLoopsInSed#Branching#Loops#Sed#Needs#Git#StudyNotes#SkillVeris