views:

275

answers:

6

Suppose I have:

my $string = "one.two.three.four";

How should I play with context to get the number of times the pattern found a match (3)? Can this be done using a one-liner?

I tried this:

my ($number) = scalar($string=~/\./gi);

I thought that by putting parentheses around $number, I'd force array context, and by the use of scalar, I'd get the count. However, all I get is 1.

+4  A: 

Try this:


my $string = "one.two.three.four";
my ($number) = scalar( @{[ $string=~/\./gi ]} );

It returns 3 for me. By creating a reference to an array the regular expression is evaluated in list context and the @{..} de-references the array reference.

PP
You don't need any of those parenthesis.
Brad Gilbert
+13  A: 

That puts the regex itself in scalar context, which isn't what you want. Instead, put the regex in list context (to get the number of matches) and put that into scalar context.

 my $number =()= $string =~ /\./gi;

Dirty joke:

What's the name of the =()= idiom?

The goatse operator.

friedo
+6  A: 

I think the clearest way to describe this would be to avoid the instant-cast to scalar. First assign to an array, and then use that array in scalar context. That's basically what the = () = idiom will do, but without the (rarely used) idiom:

my $string = "one.two.three.four";
my @count = $string =~ /\./g;
print scalar @count;
Robert P
+1 for the most straightforward way, goatse operator is scary.
kemp
Parentheses around `@count` are unnecessary though.
kemp
+8  A: 

Also, see Perlfaq4 :

There are a number of ways, with varying efficiency. If you want a count of a certain single character (X) within a string, you can use the tr/// function like so:

$string = "ThisXlineXhasXsomeXx'sXinXit";
$count = ($string =~ tr/X//);
print "There are $count X characters in the string";

This is fine if you are just looking for a single character. However, if you are trying to count multiple character substrings within a larger string, tr/// won't work. What you can do is wrap a while() loop around a global pattern match. For example, let's count negative integers:

$string = "-9 55 48 -2 23 -76 4 14 -44";
while ($string =~ /-\d+/g) { $count++ }
print "There are $count negative numbers in the string";

Another version uses a global match in list context, then assigns the result to a scalar, producing a count of the number of matches.

$count = () = $string =~ /-\d+/g;
Robert P
A: 

another way,

my $string = "one.two.three.four";
@s = split /\./,$string;
print scalar @s - 1;
+3  A: 

Is the following code a one-liner?

print $string =~ s/\./\./g;
Mike
Nice one. Thanks!
Geo