2012-08-10 33 views

回答

3

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

+3

耶!五*赞成*你不能*。我必须更努力! – Borodin 2012-08-10 14:52:57

+0

甚至可以在正则表达式中完成。看到我的答案。 – ikegami 2012-08-10 15:27:50

+0

负面的“AFAIK”答案基本上总是一个糟糕的发布选择。如果你不能解释为什么它是不可能的,为什么告诉他们你认为它是? – Mark 2012-08-10 16:31:00

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 
0

首先一句话:由于*的贪婪,最后[^a]+将不会匹配超过一个非字符 - 也就是说,你可以放弃+

而@mvf表示,您需要捕获通配符匹配的字符串,以便能够对其中的字符进行计数。 Perl正则表达式没有办法返回特定组匹配次数的计数 - 引擎可能会保留数字以支持{,n}机制,但您无法了解它。

2

有实验,鸵鸟政策的用我的,(?{ code })结构...

man perlre

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

如果没有吓跑你,这里才是最重要的 “P” S

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

产生不正确的结果,因为您没有考虑回溯。 (应该为'ppppp'和'pppppa'返回4,但返回5.) – ikegami 2012-08-10 15:19:37

+0

此外,使用在'(?{})'内部在'(?{})'之外声明的'my'变量将导致错误的结果在某些情况下。使用“我们的本地”而不是“我的”。 – ikegami 2012-08-10 15:22:55

+0

这两点都不错。我承认我在写这个例子之前从未使用这个功能。我确实看到了有关使用本地处理回溯的说明。我不知道为什么我发布了这个答案;我不会推荐使用这个,但是认为它足够有趣,可以指出。 – chepner 2012-08-10 15:29:58

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'}; 
+0

尝试在Perl之外运行'独立'代码:)(sed,awk,bash - 请参阅作者标签)。 ;)不要把使用regexp本身的Regexp'扩展'语法内部的一些Perl代码运行的能力混乱。 – mvf 2012-08-13 13:22:27

+1

@mvf,写一个在所有这些解释器中运行的问题是不可能的,所以这是没有意义的。 (* - 你可以写一个“quine”,但是这也会涉及用多种语言编写程序。) – ikegami 2012-08-16 03:41:02

3

沿鲍罗廷的溶液的线去,这里是一个纯的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计数字符的显示。我想尽可能简化解决方案。