假设我有:
my $string = "one.two.three.four";
我应该如何处理上下文以获取模式找到匹配项的次数(3)?可以使用单线吗?
我尝试了这个:
my ($number) = scalar($string=~/\./gi);
我以为通过加括号$number
,可以强制使用数组上下文,使用scalar
可以得到计数。但是,我得到的只是1
。
Answers:
这会将正则表达式本身置于标量上下文中,这不是您想要的。相反,将正则表达式放在列表上下文中(以获取匹配数),然后将其放入标量上下文中。
my $number = () = $string =~ /\./gi;
() = $string =~ /\./gi
使match运算符在列表上下文中返回匹配结果。这类似于my @results = $string =~ /\./gi;
。接下来,该my $number
部分是标量值。将列表上下文的结果分配给标量将返回其长度。这与相同my $count = @some_list
,返回数组的长度。我在下面的回答是在此处可视化行为的另一种方式。
我认为描述此问题的最清晰方法是避免即时转换为标量。首先分配给一个数组,然后在标量上下文中使用该数组。这基本上就是该= () =
成语将要执行的操作,但是没有(很少使用)成语:
my $string = "one.two.three.four";
my @count = $string =~ /\./g;
print scalar @count;
@count
是不必要的。
另外,请参阅Perlfaq4:
有多种方法,效率各不相同。如果要对字符串中的某个单个字符(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;
我注意到,如果您在正则表达式(例如/(K..K)|(V.AK)/gi
)中具有OR条件,则生成的数组可能具有未定义的元素,这些元素包括在末尾的计数中。
例如:
my $seq = "TSYCSKSNKRCRRKYGDDDDWWRSQYTTYCSCYTGKSGKTKGGDSCDAYYEAYGKSGKTKGGRNNR";
my $regex = '(K..K)|(V.AK)';
my $count = () = $seq =~ /$regex/gi;
print "$count\n";
给出的计数值为6。
我在这篇文章中找到了解决方案 如何从数组中删除所有undef?
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";
然后给出正确的答案三。
Friedo的方法是:$a = () = $b =~ $c
。
但是有可能将其简化为just ($a) = $b =~ $c
,如下所示:
my ($matchcount) = $text =~ s/$findregex/ /gi;
您只需要将其包装在函数中就可以了,getMatchCount()
不必担心会破坏传递的字符串。
另一方面,您可以添加一个交换,这可能需要更多的计算,但不会导致更改字符串。
my ($matchcount) = $text =~ s/($findregex)/$1/gi;