Butterfly Operator
Two characters. That's all it takes to turn a per-line loop into a summarizer:The butterfly operator. Also called the Eskimo greeting (turn your head sideways, it's two people rubbing noses). Discovered by Abigail in 1997 after reading about Perl's -n and -p switches.}{
It's not really an operator. It's an exploit. And it only works in one-liners.
Part 1: THE TRICK
When you run:Perl actually generates this code:perl -lne '$sum += $_ }{ print $sum' numbers.txt
See what happened? The }{ split the generated while loop in half.LINE: while (defined($_ = <ARGV>)) { chomp; $sum += $_; } { print $sum; }
The first part runs for every line. The second part runs once, at the end.
It's a makeshift END block hidden inside a one-liner.
Part 2: HOW IT WORKS
The -n switch wraps your code in:When your code contains }{, it becomes:LINE: while (defined($_ = <ARGV>)) { YOUR_CODE_HERE }
The while loop finishes. Then the bare block runs. Once.LINE: while (defined($_ = <ARGV>)) { code_before } # <-- The } closes the while loop { # <-- The { starts a bare block code_after } # <-- Perl's implicit closing brace
.--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/
Part 3: WHY ONE-LINERS ONLY
Try putting }{ in a regular script:Perl chokes. There's no implicit while loop to close.#!/usr/bin/env perl $sum += $_ }{ print $sum; # SYNTAX ERROR
The butterfly only works because -n and -p generate code that contains a brace waiting to be matched. Without that generated structure, }{ is just a confused pair of brackets.
Part 4: CLASSIC EXAMPLES
Sum all numbers in a file:How it works:perl -lne '$sum += $_ }{ print $sum' numbers.txt
Find the longest line:* Each line: add to $sum * After all lines: print total
How it works:perl -lne '$max = length if length > $max }{ print $max' file.txt
Count non-empty lines:* Each line: update $max if current line is longer * After all lines: print the maximum
How it works:perl -lne '$count++ if /\S/ }{ print $count' file.txt
Average of numbers:* Each line: increment if it contains non-whitespace * After all lines: print the count
How it works:perl -lne '$sum += $_; $n++ }{ print $sum/$n' numbers.txt
* Each line: accumulate sum and count * After all lines: divide for average
Part 5: THE ANATOMY
Every butterfly one-liner has this structure:The -l switch auto-chomps input and adds newlines to output. Almost always what you want with }{.perl -lne 'LOOP_CODE }{ END_CODE' file LOOP_CODE Runs for each line (accumulate, filter, count) }{ The butterfly - splits loop from summary END_CODE Runs once after all input (print, report, summarize)
Part 6: WITH -p INSTEAD OF -n
The -p switch also prints each line after processing. Combined with }{, you get both transformation AND summary:Output:perl -lpe '$sum += $_ }{ print "Total: $sum"' numbers.txt
Each number prints as-is, then the summary appears at the end.5 10 15 Total: 30
You can even suppress the per-line output by clearing $_:
Output:perl -lpe '$sum += $_; $_ = "" }{ print "Total: $sum"' numbers.txt
Same result as -n, but using -p's machinery.Total: 30
Part 7: MULTIPLE SUMMARIES
Nothing stops you from doing complex end-of-file logic:Full statistical summary in a "one-liner" (okay, it's wrapped for readability, but it's still one perl command).perl -lne ' $sum += $_; $count++; $min = $_ if !defined $min || $_ < $min; $max = $_ if !defined $max || $_ > $max; }{ print "Count: $count"; print "Sum: $sum"; print "Min: $min"; print "Max: $max"; print "Avg: " . ($sum/$count); ' numbers.txt
Part 8: THE NAME
Why "butterfly"? Look at }{ and tilt your head:Wings spread. Antennae up. It's a stretch, but Perl folks love their whimsical names.}{ ^ / \ / \ | | / \
The "Eskimo greeting" name comes from rotating it 90 degrees:
Two faces touching noses. Traditional Inuit greeting. Also a stretch.} {
Both names stuck because they're memorable. Nobody wants to say "the implicit loop terminator with trailing bare block."
Part 9: REAL-WORLD USES
Word frequency count:Unique line count:perl -lne '$h{$_}++ for split /\s+/ }{ print "$_: $h{$_}" for sort keys %h' file.txt
First and last line:perl -lne '$seen{$_}++ }{ print scalar keys %seen' file.txt
File size in lines and bytes:perl -lne '$first //= $_; $last = $_ }{ print "First: $first\nLast: $last"' file.txt
Note: $. is the line number, which equals total lines at EOF.perl -lne '$bytes += length; }{ print "Lines: $.\nBytes: $bytes"' file.txt
Part 10: HISTORICAL NOTE
The butterfly appeared shortly after The Perl Journal published an interview with Chip Salzenberg explaining -n and -p internals.Abigail, legendary Perl hacker and regex wizard, saw the generated code structure and realized }{ would exploit it. The technique spread through the Perl community as a clever party trick that turned out to be genuinely useful.
It's a reminder that Perl's quirks aren't bugs. They're features waiting to be discovered.
}{ / \ / \ | >< | \ / \ / \/ "Close one door, open another" - Perl proverb
Created By: Wildcard Wizard. Copyright 2026