2013-06-26 45 views
0

我的意思是在Perl的正則表達式匹配,是有可能知道在{N,}

匹配的數目例如是{3,}將greedly匹配「a」中的至少3倍。它可能會找到5次,10次等我需要這個號碼。我需要這個數字代碼的其餘部分。如果不知道它,我可以做得更低效,但我想也許Perl有一些內置的變量來給這個數字,或者你可能知道一些竅門來得到它。感謝

+0

我不是Perl用戶,但你可以不捕獲它,分配給一個變量,然後找到它的長度?似乎對我來說很簡單 – ydaetskcoR

+0

你問同樣的問題,因爲http://stackoverflow.com/questions/3610295/perl-regex-how-to-know-number-of-matches? –

+1

聽起來像一個XY問題。也許你應該問一下你需要這個長度的原因。 – TLP

回答

0

如果你有/AB{n,}/類型的圖案,其中一個是複雜的模式,我們可以將正則表達式分成多個部分:

my $string = "ABABBBB"; 
my $n = 3; 

my $count = 0; 
TRY: 
while ($string =~ /A/gc) { 
    my $pos = pos $string; # remember position for manual backtracking 
    $count++ while $string =~ /\GB/g; 
    if ($count < $n) { 
    $count = 0; 
    pos($string) = $pos; # restore previous position 
    } else { 
    last TRY; 
    } 
} 
say $count; 

輸出:4

然而,將代碼嵌入到正則表達式中進行計數可能更爲理想,因爲它更爲通用:

my $string = "ABABBBB"; 
my $count; 
$string =~ /A(?{ $count = 0 })(?:B(?{ $count++ })){3,}/ and say $count; 

輸出:4

缺點是這段代碼不能運行在較老的perls上。 (代碼已在v14 & v16上測試過)。


編輯:如果B圖案回溯第一個解決方案會失敗,例如$B = qr/BB?/。該模式應該匹配ABABBBB字符串三次,但策略只會讓它匹配兩次。使用嵌入代碼的解決方案允許正確的回溯。

+0

謝謝,我會玩它,並嘗試適應我的需要,再次感謝給我的想法分裂正則表達式 – user2475407

2

只是捕獲它並使用length

if (/(a{3,})/) { 
    print length($1), "\n"; 
} 
0

這裏有一個想法(也許這是你已經有了嗎?)假設你有興趣計數模式有多個字符和可變長度:

  • 捕獲該pattern{3,}子模式相匹配的子串
  • 然後根據pattern(注意缺少量詞)全局匹配捕獲的子字符串,並在=~上強制列表上下文以獲取匹配數。

下面是一個示例代碼來說明這一點(這裏$patt是你感興趣的計數的子模式)

my $str = "some catbratmatrattatblat thing"; 
my $patt = qr/b?.at/; 

if ($str =~ /some ((?:$patt){3,}) thing/) { 
    my $count =() = $1 =~ /$patt/g; 
    print $count; 
    ... 
} 

另一個(誠然有點微不足道),例如有2個子模式

my $str = "some catbratmatrattatblat thing 11,33,446,70900,"; 
my $patt1 = qr/b?.at/; 
my $patt2 = qr/\d+,/; 

if ($str =~ /some ((?:$patt1){3,}) thing ((?:$patt2){2,})/) { 
    my ($substr1, $substr2) = ($1, $2); 
    my $count1 =() = $substr1 =~ /$patt1/g; 
    my $count2 =() = $substr2 =~ /$patt2/g; 
    say "count1: " . $count1; 
    say "count2: " . $count2; 
} 

此方法的侷限性:

失敗悲慘與lookarounds。見amon's example

+1

周圍可以使這種策略失敗:'$ str =「A,B,B,B,C」; $ patt = qr /(?<=,)B,/;'。正則表達式:'/ A,($ patt {3,})C /'。輸出:'2'。順便說一下,'$ patt'內的捕獲組不會影響結果。 – amon

+0

@amon,謝謝,我會記下它。 – doubleDown