计算与正则表达式通配符匹配的字符串中特定字符的匹配数

时间:2012-08-10 14:23:36

标签: regex perl bash sed awk

我可以保留正则表达式本身中匹配的每个不同字符的数量吗?

假设正则表达式看起来像/>(.*)[^a]+/

我是否可以对小组p捕获的字符串中的字母(.*)进行计数?

6 个答案:

答案 0 :(得分: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

答案 1 :(得分: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'};

答案 2 :(得分:3)

AFAIK,你做不到。您只能通过括号捕获某些组,然后检查该组捕获的数据长度。

答案 3 :(得分:3)

按照鲍罗丁的解决方案,这里是一个纯粹的打击:

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计数字符的显示。我想让解决方案尽可能简单。

答案 4 :(得分:2)

有实验性的,不使用我,(?{ code })构造......

来自man perlre

  

“(?{code})”    警告:此扩展正则表达式功能被认为是实验性的,可能是    更改,恕不另行执行的具有副作用的代码可能执行不相同    由于未来优化在正则表达式引擎中的影响,从版本到版本。

如果这没有让你害怕,这里有一个计算“p”的数量的例子

my $p_count;
">pppppbca" =~ /(?{ $p_count = 0 })>(p(?{$p_count++})|.)*[^a]+/;
print "$p_count\n";

答案 5 :(得分:0)

首先评论一下:由于*的贪婪,最后[^a]+将永远不会匹配多个非字符 - 也就是说,您可能会删除+

正如@mvf所说,你需要捕获通配符匹配的字符串,以便能够计算其中的字符数。 Perl正则表达式无法返回特定组匹配的次数 - 引擎可能会保留数字以支持{,n}机制,但是您无法获得它。