2012-08-10 95 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計數字符的顯示。我想盡可能簡化解決方案。