9

正規表現自体で一致する各文字のカウントを保持できますか?

正規表現が次のようになるとします/>(.*)[^a]+/

pグループによってキャプチャされた文字列内の文字など、出現回数を数えることはできます(.*)か?

4

6 に答える 6

5

正規表現の外:

my $p_count = map /p/g, />(.*)[^a]/;

自己完結型:

local our $p_count;
/
   (?{ 0 })
   >
   (?: p (?{ $^R + 1 })
   |   [^p]
   )*
   [^a]
   (?{ $p_count = $^R; })
/x;

どちらの場合も、これを簡単に拡張してすべての文字を数えることができます。例えば、

my %counts;
if (my ($seq = />(.*)[^a]/) {
   ++$counts{$_} for split //, $seq;
}

my $p_count = $counts{'p'};
于 2012-08-10T15:26:54.397 に答える
5

一致した文字列をキャプチャして、個別に処理する必要があります。

このコードは

use strict;
use warnings;

my $str = '> plantagenetgoosewagonattributes';

if ($str =~ />(.*)[^a]+/) {
  my $substr = $1;
  my %counts;
  $counts{$_}++ for $substr =~ /./g;
  print "'$_' - $counts{$_}\n" for sort keys %counts;
}

出力

' ' - 1
'a' - 4
'b' - 1
'e' - 4
'g' - 3
'i' - 1
'l' - 1
'n' - 3
'o' - 3
'p' - 1
'r' - 1
's' - 1
't' - 5
'u' - 1
'w' - 1
于 2012-08-10T14:45:45.020 に答える
3

私の知る限り、できません。一部のグループのみを括弧でキャプチャし、後でそのグループによってキャプチャされたデータの長さを確認できます。

于 2012-08-10T14:30:28.210 に答える
3

Borodin's solution の行に沿って進むと、ここに純粋な bash があります。

let count=0  
testarray=(a b c d e f g h i j k l m n o p q r s t u v w x y z) 

string="> plantagenetgoosewagonattributes"                 # the string 
pattern=">(.*)[^a]+"                                   # regex pattern

limitvar=${#testarray[@]}                                  #array length

[[ $string =~ $pattern ]] && 
( while [ $count -lt $limitvar ] ; do sub="${BASH_REMATCH[1]//[^${testarray[$count]}]}" ; echo "${testarray[$count]} = ${#sub}" ; ((count++)) ; done )

bash 3.0 以降、bash は BASH_REMATCH[n] を介してアクセスできるキャプチャ グループを導入しました。

ソリューションでは、文字を配列としてカウントすることを宣言します [declare -a複雑なケースでは配列宣言を確認してください]。

上記のコードのように範囲を含める場合、この配列宣言は正確に行われます。

testarray=(`echo {a..z}`)

if ループの導入により、0count 文字の表示が考慮されます。ソリューションをできるだけシンプルにしたかったのです。

于 2012-08-16T10:02:07.350 に答える
2

実験的な、私を使わない、(?{ code })構造があります...

からman perlre:

"(?{ code })" 警告: この拡張正規表現機能は実験的なものであり、予告なしに変更される可能性があります。副作用のある実行コードは、正規表現エンジンでの将来の最適化の影響により、バージョン間で同じように実行されない場合があります。

それでも怖がらなければ、「p」の数を数える例を次に示します。

my $p_count;
">pppppbca" =~ /(?{ $p_count = 0 })>(p(?{$p_count++})|.)*[^a]+/;
print "$p_count\n";
于 2012-08-10T15:08:51.160 に答える
0

最初の注意: * は貪欲であるため、最後[^a]+の文字は複数の非 a 文字に一致することはありません+

@mvf が言ったように、ワイルドカードが一致する文字列をキャプチャして、その中の文字をカウントできるようにする必要があります。Perl の正規表現には、特定のグループが一致した回数を返す方法がありません。おそらくエンジンは{,n}メカニズムをサポートするために数を保持していますが、それを取得することはできません。

于 2012-08-10T15:03:04.293 に答える