web-dev-qa-db-ja.com

文字列内の一致数をカウントするPerlショートカットはありますか?

私が持っていると仮定します:

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

パターンが一致を見つけた回数を取得するために、どのようにコンテキストを再生する必要がありますか(3)?これはワンライナーを使用して実行できますか?

私はこれを試しました:

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

$numberを括弧で囲むことにより、配列コンテキストを強制し、scalarを使用することで、カウントを取得すると思いました。ただし、取得できるのは1だけです。

74
Geo

これにより、正規表現自体がスカラーコンテキストになりますが、これは望みではありません。代わりに、正規表現をリストコンテキストに入れて(一致数を取得するため)、thatをスカラーコンテキストに入れます。

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

これを説明する最も明確な方法は、スカラーへのインスタントキャストを避けることだと思います。最初に配列に割り当ててから、その配列をスカラーコンテキストで使用します。これは基本的に= () =イディオムが行うことですが、(めったに使用されない)イディオムはありません:

my $string = "one.two.three.four";
my @count = $string =~ /\./g;
print scalar @count;
32
Robert P

また、 Perlfaq4 を参照してください:

さまざまな効率の方法がいくつかあります。文字列内の特定の1文字(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;
20
Robert P

次のコードはワンライナーですか?

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

これを試して:


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

3を返します。配列への参照を作成することにより、正規表現はリストコンテキストで評価され、@{..}は配列参照を逆参照します。

6
PP.

正規表現にOR条件(たとえば/(K..K)|(V.AK)/gi))がある場合、生成される配列には未定義の要素があり、最後にカウントに含まれることがあります。

例えば:

my $seq = "TSYCSKSNKRCRRKYGDDDDWWRSQYTTYCSCYTGKSGKTKGGDSCDAYYEAYGKSGKTKGGRNNR";
my $regex = '(K..K)|(V.AK)';
my $count = () = $seq =~ /$regex/gi;
print "$count\n";

Countの値を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";

これにより、3つの正解が得られます。