Arrays 是否有Perl快捷方式来计算字符串中的匹配数?

Arrays 是否有Perl快捷方式来计算字符串中的匹配数?,arrays,regex,perl,perl4,Arrays,Regex,Perl,Perl4,假设我有: my $string = "one.two.three.four"; 我应该如何使用上下文来获取模式找到匹配项的次数(3)?这可以用一个衬垫来完成吗 print $string =~ s/\./\./g; 我试过这个: my ($number) = scalar($string=~/\./gi); 我认为通过在$number周围加括号,我可以强制数组上下文,通过使用标量,我可以得到计数。然而,我得到的只是1试试这个: my $string = "one.two.three.f

假设我有:

my $string = "one.two.three.four";
我应该如何使用上下文来获取模式找到匹配项的次数(3)?这可以用一个衬垫来完成吗

print $string =~ s/\./\./g;
我试过这个:

my ($number) = scalar($string=~/\./gi);
我认为通过在
$number
周围加括号,我可以强制数组上下文,通过使用
标量,我可以得到计数。然而,我得到的只是
1

试试这个:


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

它为我返回
3
。通过创建对数组的引用,正则表达式在列表上下文中求值,而
@{..}
反引用数组引用。

将正则表达式本身置于标量上下文中,这不是您想要的。相反,将正则表达式放在列表上下文中(以获取匹配数),并将其放在标量上下文中

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

我认为描述这一点最清晰的方式是避免对标量的瞬间转换。首先分配给数组,然后在标量上下文中使用该数组。这基本上就是
=()=
习惯用法所能做的,但是没有(很少使用的)习惯用法:

另见:

有很多方法,效率各不相同。如果希望在字符串中计算某个单个字符(X)的计数,可以使用tr///函数,如下所示:

$string = "ThisXlineXhasXsomeXx'sXinXit";
$count = ($string =~ tr/X//);
print "There are $count X characters in the string";
如果你只是在寻找一个角色,这是很好的。但是,如果您试图在一个较大的字符串中计算多个字符的子字符串,tr///将不起作用。您可以做的是围绕全局模式匹配进行while()循环。例如,让我们计算负整数:

$string = "-9 55 48 -2 23 -76 4 14 -44";
while ($string =~ /-\d+/g) { $count++ }
print "There are $count negative numbers in the string";
另一个版本在列表上下文中使用全局匹配,然后将结果分配给标量,生成匹配数的计数

$count = () = $string =~ /-\d+/g;
另一方面,

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

以下代码是一行代码吗

print $string =~ s/\./\./g;

弗里多的方法是:
$a=()=$b=~$c

但可以进一步简化为
($a)=$b=~$c
,如下所示:

my ($matchcount) = $text =~ s/$findregex/ /gi;
您只需将其封装在函数中,
getMatchCount()
,而不用担心它会破坏传递的字符串

另一方面,您可以添加交换,这可能需要更多的计算,但不会改变字符串

my ($matchcount) = $text =~ s/($findregex)/$1/gi;

通过Benchmark检查,速度非常快

我注意到,如果正则表达式中有OR条件(例如
/(K..K)|(V.AK)/gi
),那么生成的数组可能包含未定义的元素,这些元素包含在最后的计数中

例如:

my $seq = "TSYCSKSNKRCRRKYGDDDDWWRSQYTTYCSCYTGKSGKTKGGDSCDAYYEAYGKSGKTKGGRNNR";
my $regex = '(K..K)|(V.AK)';
my $count = () = $seq =~ /$regex/gi;
print "$count\n";
给出计数为6的值

我在这篇文章中找到了解决办法


这就给出了三的正确答案。

+1最简单的方法是,goatse运算符很可怕。
@count
周围的括号是不必要的。你不需要任何括号。我必须说我比goatse更喜欢这种方法。事实上,我比goatse更喜欢任何东西。好吧,perlsecret确实建议用“Saturn”作为另一个名字有人能给我解释一下这段代码吗?我是perl新手,对上下文还是不太熟悉。第一部分,
()=$string=~/\./gi
,让match操作符在列表上下文中返回匹配结果。这类似于
my@results=$string=~/\./gi。接下来,
my$number
部分是一个标量值。将列表上下文的结果分配给标量将返回其长度。这与返回数组长度的
my$count=@some_list
相同。下面我的回答是另一种可视化行为的方法。除了这是替换,而不是匹配:它将破坏原始字符串。这和六年前的“迈克”的想法是一样的。@fishinear:这和迈克的想法大不相同。他能够打印它,但不能将其存储到变量中。差别很大。如果你需要无损检测,只要s/(regex)/$1/g或/(=regex)//g,如果你喜欢危险的生活。@android.weasel哦,嘿,说得好!用这句话更新。我通常在函数中封装这样的东西,所以我自己不必担心传递的参数的可破坏性(不确定哪个更快,因为现在它正在进行交换)。但这是有用的信息,添加!这不是模式匹配。
my $seq = "TSYCSKSNKRCRRKYGDDDDWWRSQYTTYCSCYTGKSGKTKGGDSCDAYYEAYGKSGKTKGGRNNR";
my $regex = '(K..K)|(V.AK)';
my $count = () = $seq =~ /$regex/gi;
print "$count\n";
my $seq = "TSYCSKSNKRCRRKYGDDDDWWRSQYTTYCSCYTGKSGKTKGGDSCDAYYEAYGKSGKTKGGRNNR";
my $regex = '(K..K)|(V.AK)';
my @count = $seq =~ /$regex/gi;
@count = grep defined, @count; 
my $count = scalar @count;
print "$count\n";