正規表現自体で一致する各文字のカウントを保持できますか?
正規表現が次のようになるとします/>(.*)[^a]+/
p
グループによってキャプチャされた文字列内の文字など、出現回数を数えることはできます(.*)
か?
正規表現の外:
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'};
一致した文字列をキャプチャして、個別に処理する必要があります。
このコードは
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
私の知る限り、できません。一部のグループのみを括弧でキャプチャし、後でそのグループによってキャプチャされたデータの長さを確認できます。
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
ループの導入により、0
count 文字の表示が考慮されます。ソリューションをできるだけシンプルにしたかったのです。
実験的な、私を使わない、(?{ code })
構造があります...
からman perlre
:
"(?{ code })" 警告: この拡張正規表現機能は実験的なものであり、予告なしに変更される可能性があります。副作用のある実行コードは、正規表現エンジンでの将来の最適化の影響により、バージョン間で同じように実行されない場合があります。
それでも怖がらなければ、「p」の数を数える例を次に示します。
my $p_count;
">pppppbca" =~ /(?{ $p_count = 0 })>(p(?{$p_count++})|.)*[^a]+/;
print "$p_count\n";
最初の注意: * は貪欲であるため、最後[^a]+
の文字は複数の非 a 文字に一致することはありません+
。
@mvf が言ったように、ワイルドカードが一致する文字列をキャプチャして、その中の文字をカウントできるようにする必要があります。Perl の正規表現には、特定のグループが一致した回数を返す方法がありません。おそらくエンジンは{,n}
メカニズムをサポートするために数を保持していますが、それを取得することはできません。