The Flip-Flop Operator: Perl's Weirdest Gift to Ruby
Ruby inherited Perl's flip-flop operator directly. It's a stateful boolean that turns true when the first condition matches and stays true until the second condition matches. If you've ever usedprint if /START/ .. /END/ in Perl, congratulations, you already know this one. If you haven't, prepare to have your mind slightly bent.
Part 1: Basic Usage
Identical behavior in both languages. The flip-flop remembers its state between iterations.# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Print lines between START and END markers # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ARGF.each_line do |line| puts line if line =~ %r~START~ .. line =~ %r~END~ end # Perl: perl -ne 'print if /START/ .. /END/' # Ruby: ruby -ne 'puts $_ if /START/ .. /END/'
Part 2: How It Works
The flip-flop has two states:- Off: Evaluates only the LEFT condition. When left becomes true, switches to "on" state.
- On: Evaluates only the RIGHT condition. When right becomes true, switches back to "off" state.
The line that triggers each transition IS included in the output. So you get the START line, everything in between, and the END line.
Part 3: Two Dots vs Three Dots
..(two dots): Checks the end condition on the SAME line that the start matched...(three dots): Doesn't check the end condition until the NEXT iteration
In practice you almost always want# With .. (two dots): # If START and END appear on the SAME line, it matches just that line puts line if line =~ %r~START~ .. line =~ %r~END~ # With ... (three dots): # Even if END appears on the START line, it won't stop until a later END puts line if line =~ %r~START~ ... line =~ %r~END~
... The ... variant is for when your markers might overlap on a single line and you want to keep going.
Part 4: Line Number Ranges
# Print lines 3 through 15 ARGF.each_line do |line| puts line if ($. == 3)..($. == 15) end # One-liner version: ruby -ne 'puts $_ if ($. == 3)..($. == 15)' file.txt
Part 5: Practical Examples
Extract a section from an INI config file:Extract between timestamps in a log:# Extract [database] section from INI file ARGF.each_line do |line| puts line if line =~ %r~\[database\]~ .. line =~ %r~^\[~ end
Extract block content:# Print log lines between two times ARGF.each_line do |line| puts line if line =~ %r~10:00:00~ .. line =~ %r~11:00:00~ end
# Print content between BEGIN and END markers in a config ARGF.each_line do |line| puts line if line =~ %r~^BEGIN~ .. line =~ %r~^END~ end
Part 6: Gotchas
- The flip-flop is STATEFUL. It remembers its state between iterations.
- Each flip-flop instance has its own state.
- The start and end lines ARE included in the output.
- If the start condition never matches, nothing is output.
- If the start matches but end never does, everything from start to EOF is output.
Part 7: One-Liner Examples
The flip-flop is one of those operators that seems obscure until you need to extract a section from a file. Then it's the only tool you want.# Extract lines between markers ruby -ne 'puts $_ if /BEGIN/../END/' file.txt # Print lines 5-10 ruby -ne 'puts $_ if ($. == 5)..($. == 10)' file.txt # Extract Apache virtual host config ruby -ne 'puts $_ if /VirtualHost/../\/VirtualHost/' httpd.conf
Created By: Wildcard Wizard. Copyright 2026