Goatse Operator
This page explains the=()= operator in Perl, which forces list context so you can count matches, splits, or list elements in a single expression:
The goatse operator. The name is exactly what you think it is. Turn your head sideways and squint a little. Perl hackers have a dark sense of humor.=()=
The operator itself is genuinely useful, so the name should not distract you from what it does.
Part 1: THE TRICK
How many words in a string?That is all you need.my $count = () = $string =~ m~\w+~g;
$count now holds the number of matches.
Without the =()= wrapper:
That gives youmy $count = $string =~ m~\w+~g;
1 (true) or 0 (false). You get a boolean, not a count.
The goatse forces list context on the regex, so the regex returns every match instead of a single truth value. The assignment then returns the count of that list.
Part 2: HOW IT WORKS
Break it down piece by piece:The magic is the empty parentheses. When you assign a list tomy $count = () = $string =~ m~\w+~g; PIECE WHAT IT DOES ------------------ ------------------------------------------ $string =~ m~\w+~g Match all words, return list of matches () = Assign to empty list (forces list context) my $count = Assign the COUNT of that list to $count
(), Perl evaluates the right side in list context but throws away the actual values. What propagates leftward is the count.
It is the same reason this works:
my $count = () = (1, 2, 3, 4, 5); # $count is 5 .--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/
Part 3: COUNTING MATCHES
Count vowels in a string:Count IP addresses in a log:my $text = "The quick brown fox"; my $vowels = () = $text =~ m~[aeiou]~gi; print "Vowels: $vowels\n"; # Vowels: 5
Count lines matching a pattern:my $log = slurp('access.log'); my $ips = () = $log =~ m~\d+\.\d+\.\d+\.\d+~g; print "Found $ips IP addresses\n";
my @lines = <FILE>; my $errors = () = grep { m~ERROR~ } @lines; print "Error count: $errors\n";
Part 4: COUNTING SPLITS
How many fields in a CSV line?Count path components:my $line = "one,two,three,four,five"; my $fields = () = split m~,~, $line; print "Fields: $fields\n"; # Fields: 5
Note thatmy $path = "/usr/local/bin/perl"; my $depth = () = split m~/~, $path; print "Depth: $depth\n"; # Depth: 5
split returns empty strings for leading delimiters, so /usr gives you ("", "usr", "local", "bin", "perl") which is five elements.
Part 5: IN ONE-LINERS
Count words in a file:Theperl -0777 -ne 'print scalar(() = m~\w+~g), "\n"' file.txt
scalar() is needed because print provides list context. We want the count, not the matches.
Count matches per line:
Output:perl -lne '$n = () = m~the~gi; print "$n: $_"' file.txt
2: The cat and the dog 0: No matches here 1: Another the appears
Part 6: WHY NOT JUST USE SCALAR?
You might think:That does not work. Themy $count = scalar($string =~ m~\w+~g);
scalar() does not change the context of the regex match. It just converts the result. You still get 1 or 0.
The goatse works because the assignment to () happens before the assignment to $count. Context flows right to left in Perl.
my $count = () = $string =~ m~\w+~g; ^ | This assignment forces list context on everything to its right
Part 7: VARIATIONS
Sometimes you see it written with variables instead of empty parens:That has the same effect, butmy $count = my @dummy = $string =~ m~\w+~g;
@dummy now holds the actual matches. Use that form when you want both the count and the matched strings.
Or with the //g in different positions:
That is the statement modifier form. It returns the same count.my $count = () = m~pattern~g for $string;
Part 8: GOTCHAS
Watch out for captures:With captures, you get the captured parts. Without captures, you get the full matches. The count is the same here, but the actual strings differ.my $text = "abc 123 def 456"; my $count = () = $text =~ m~(\w+)~g; # $count is 4 (the captured groups) my $count = () = $text =~ m~\w+~g; # $count is also 4 (the full matches)
Multiple captures multiply your count:
my $count = () = $text =~ m~(\w)(\w)~g; # $count is 8 (two captures x four matches)
Part 9: REAL-WORLD USES
Validate credit card format (count digits):Count function calls in code:my $cc = "4111-1111-1111-1111"; my $digits = () = $cc =~ m~\d~g; die "Invalid card" unless $digits == 16;
Check minimum word count:my $code = slurp('script.pl'); my $prints = () = $code =~ m~\bprint\b~g; print "Found $prints print statements\n";
my $essay = <STDIN>; my $words = () = $essay =~ m~\w+~g; die "Too short!" if $words < 500;
Part 10: THE NAME
I am not going to explain the name. If you do not know, consider yourself lucky. If you do know, I am sorry.Some people call it the "saturn operator" because it looks like the planet with rings. Others call it the "countof operator" because that describes what it does. The name goatse stuck, because Perl culture is what it is.
The operator itself is elegant. The name is memorable.
perl.gg=( )= | count | \_____/ Forcing list context since 1997