perl.gg / secret-operators

Flip-flop Operator

2026-01-15

You know .. as the range operator:
my @nums = (1 .. 5); # (1, 2, 3, 4, 5)
But in scalar context, it becomes something completely different:
..
The flip-flop operator. It remembers state between calls. Perfect for extracting sections from files.

Part 1: THE TRICK

while (<DATA>) { print if m~START~ .. m~END~; } __DATA__ ignore this START grab this and this END ignore this too
Output:
START grab this and this END
The flip-flop "turns on" at START and "turns off" at END. Everything between gets printed.

Part 2: HOW IT WORKS

The .. operator has two states:
OFF: Returns false, waiting for left condition to be true ON: Returns true, waiting for right condition to be true
When the left side matches, it flips ON. When the right side matches, it flips OFF.

It has MEMORY. Each call remembers the previous state.

.--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/

Part 3: THE STATES IN DETAIL

LINE LEFT RIGHT STATE OUTPUT -------------------------------------------------------- ignore false - OFF (skip) START TRUE false ON-> print (just turned on) grab false false ON print (still on) and this false false ON print (still on) END false TRUE ->OFF print (turning off now) ignore false - OFF (skip)
Key insight: both the START and END lines are printed. The flip happens AFTER the match.

Part 4: LOG FILE PARSING

Extract a specific time range from logs:
while (<$log>) { print if m~\[10:00:~ .. m~\[11:00:~; }
Grabs everything from 10:00 to 11:00.

Extract a specific request:

while (<$log>) { print if m~BEGIN Request #1234~ .. m~END Request #1234~; }
Perfect for debugging specific transactions.

Part 5: LINE NUMBER RANGES

Flip-flop works with line numbers too:
while (<DATA>) { print if 3 .. 7; }
Prints lines 3 through 7.

How? In scalar context, bare numbers compare against $. (the line number). So 3 .. 7 means "line 3 through line 7."

perl -ne 'print if 5 .. 10' file.txt
One-liner: print lines 5-10.

Part 6: THE THREE-DOT VERSION

There's also ...:
while (<DATA>) { print if m~START~ ... m~END~; }
Difference: with ..., the right side isn't checked on the same line that triggered the left side.
.. Two dots: left and right can match on same line ... Three dots: left and right can't match on same line
Usually doesn't matter. But for edge cases:
# Line says "START something END" m~START~ .. m~END~ # Flips on AND off on same line m~START~ ... m~END~ # Flips on, stays on until NEXT END

Part 7: MULTIPLE RANGES

The flip-flop resets when it turns off, so you can catch multiple ranges:
while (<DATA>) { print if m~BEGIN~ .. m~END~; } __DATA__ noise BEGIN first block END more noise BEGIN second block END final noise
Output:
BEGIN first block END BEGIN second block END
Both blocks are captured.

Part 8: CONFIG FILE PARSING

Extract a section from a config:
while (<$config>) { print if m~\[database\]~ .. m~^\[~; }
From [database] until the next [section].

Gotcha: this also prints the next section header. To exclude it:

while (<$config>) { if (m~\[database\]~ .. m~^\[~) { print unless m~^\[~ and not m~\[database\]~; } }
Or process into a hash:
my %config; my $section; while (<$config>) { $section = $1 if m~^\[(\w+)\]~; $config{$section}{$1} = $2 if m~^(\w+)=(.*)~; }

Part 9: ONE-LINERS

Print between patterns:
perl -ne 'print if /START/ .. /END/' file.txt
Print lines 10-20:
perl -ne 'print if 10 .. 20' file.txt
Print from pattern to end of file:
perl -ne 'print if /START/ .. eof' file.txt
Print from start to pattern:
perl -ne 'print if 1 .. /END/' file.txt

Part 10: STATEFUL WARNING

The flip-flop has PERSISTENT state. This can bite you:
sub extract_section { my $file = shift; open my $fh, '<', $file or die; while (<$fh>) { print if m~START~ .. m~END~; } } extract_section('file1.txt'); extract_section('file2.txt'); # STATE CARRIES OVER!
If file1.txt ends without hitting END, the flip-flop stays ON for file2.txt.

Fix: reset state by reaching END, or use a different approach.

Part 11: THE NAME

Flip-flop comes from electronics. A flip-flop circuit has two stable states and switches between them based on input signals.
ON ----+ +---- ON | | v v [TRIGGER] ^ ^ | | OFF ----+ +---- OFF
Perl's .. does the same thing: flips on with one condition, flops off with another.

Part 12: PRACTICAL EXAMPLE

Extract all function definitions from Perl code:
while (<$source>) { print if m~^sub \w+~ .. m~^}~; }
From "sub name" to the closing brace.

Extract error blocks from logs:

while (<$log>) { print if m~ERROR~ .. m~^$~; }
From ERROR to the next blank line (assuming stack traces are followed by blank lines).
.. / \ ON OFF \ / \/ [MEMORY] Stateful range matching since Perl 1

Created By: Wildcard Wizard. Copyright 2026