我有一个任务是“查找包含至少 3 个零和最多 2 个 1 的字符串的数量”,而我的字母表只包含 0 和 1。我试着这样写:
(if $line =~ /0{3,}/)
但它只给了我 3 个“连续”零。
比我试过这个:
(if $line =~ /0+0+0+/)
它再次给了我连续的零。
检查所有字符串并查找该字符串中所有零的数量(无论它们是否连续)的逻辑是什么。
#match a 0 + anything + 0 + anything + 0, and not (!) 1...1...1
if (($line =~ /0.*0.*0/) && !($line =~ /1.*1.*1/) ) {
$count++;
}
如果它包含至少三个零,则它包含一个零,后跟零个或多个字符,后跟一个零,后跟零个或多个字符,然后是一个零。
$line =~ /0.*0.*0/s
-or-
$line =~ /^[^0]*0[^0]*0[^0]*0/ # More efficient for strings that don't match.
-or-
$line =~ /^(?:[^0]*0){3}/ # Avoid code repetition
如果它最多包含两个,则它不包含至少三个。
$line !~ /^(?:[^1]*1){3}/
所以,
$line =~ /^(?:[^0]*0){3}/ && $line !~ /^(?:[^1]*1){3}/
这种基于正则前瞻的正则表达式应该可以工作:
/^(?=(?:1*0){3})(?=0*(?:10*){0,2}\z)/
我会计算替换,毕竟它们是正则表达式的一部分,不是吗?
在标量上下文中,s{0}{0}g
将返回完成替换的次数,即字符串中 0 的数量。s{0}{0}g >= 3 && s{1}{1}g <=2
您正在寻找的条件也是如此。
这是一个小测试程序来测试它:
#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
while( <DATA>)
{ chomp;
my( $nb, $expected)= split /\s*=>\s*/;
# the for topicalizes $nb so we don't have to write it in the condition
for ( $nb)
{ my $got= s{0}{0}g >= 3 && s{1}{1}g <=2 ? 'ok' : 'nok';
is( $got, $expected, "testing $nb ($expected)");
}
}
done_testing();
__DATA__
00011 => ok
01010 => ok
1000 => ok
000 => ok
0000 => ok
1100000=> ok
0 => nok
00 => nok
1 => nok
11 => nok
111 => nok
10 => nok
100 => nok
1100 => nok
111000 => nok
010101 => nok