2012-02-06 16 views
6

我已經能夠找到與此類似的但不相同的問題。如何在由未知字符分隔的同一行中多次匹配一個正則表達式模式?Perl,在由未知字符分隔的同一行中多次匹配一個模式

例如,假設我想匹配HEY模式。我願意承認所有以下內容:

HEY

嘿,嘿

HEYxjfkdsjfkajHEY

所以我算5個HEYs那裏。因此,這裏是我的計劃,該計劃適用於一切,但最後一個:

open (FH, $ARGV[0]); 
while(<FH>) 
{ 
    foreach $w (split) 
    { 
     if ($w =~ m/HEY/g) 
     { 
      $count++; 
     } 
    } 
} 

所以我的問題是我怎麼替換foreach循環,使我能夠識別出未知的配置怪異字符(分隔模式,如所示上面的例子)?

編輯:

感謝迄今偉大的響應。我只是意識到我還需要其他的東西,我在下面發表評論。

雖然有一個問題:是否有任何方法來保存匹配的術語呢?所以,像我的情況,有沒有什麼辦法來引用$ W(比方說,如果正則表達式是比較複雜的,我想它出現的次數存儲在一個散)

所以,如果我是匹配真正的正則表達式(稱爲字母數字字符序列)並希望將其保存在散列表中。

回答

11

一種方法是捕獲所有匹配的字符串,看看你有多少。像這樣:

open (FH, $ARGV[0]); 
while(my $w = <FH>) { 
    my @matches = $w =~ m/(HEY)/g; 
    my $count = scalar(@matches); 
    print "$count\t$w\n"; 
} 

編輯:

是的,有!就在所有的比賽迴路,並使用捕捉變量來增加計數在哈希:

my %hash; 
open (FH, $ARGV[0]); 
while (my $w = <FH>) { 
    foreach ($w =~ /(HEY)/g) { 
     $hash{$1}++; 
    } 
} 
+0

嘿,感謝您的幫助。我實際上不得不修改你的東西,以兩種方式工作:首先,我不能爲你的解決方案讓第一部分工作,所以我使用了Wes的方法(兩個while循環)。另外,我只是想指出,在整個正則表達式中,包含一羣組的正則表達式需要(),這樣您就不會得到只包含所需總數碎片的哈希值。雖然謝謝! – varatis 2012-02-06 06:50:15

+1

你的朋友在處理多個分組時是使用問號冒號'(?:)'修改的非捕獲組。 – masaers 2012-02-08 08:05:30

5

問題是你真的不想叫拆分()。它將事物分解成單詞,並且您會注意到最後一行只有一個「單詞」(儘管您在字典中找不到它)。一個詞被白色空間限定,因此「只有空白」。

你真正想要的是繼續查看每一行的每一行,每次都是從每次停止的地方開始。這需要在/克目的,而是繼續尋找:

while(<>) 
{ 
     while (/HEY/g) 
     { 
      $count++; 
     } 
} 

print "$count\n"; 

還有就是,當然,不止一種方法做,但這個堅持貼近你的榜樣。其他人也會發布其他精彩的例子。向他們學習!

+0

嘿,這很不錯!我還沒有實現它,但它似乎應該工作。但有一個問題:還有什麼方法可以保存匹配的術語呢?所以就像我的情況一樣,是否有任何方法可以引用$ w(例如,如果正則表達式更復雜,並且我希望將它存儲在具有出現次數的散列中) – varatis 2012-02-06 06:21:04

+0

是的,這很可能。看到我編輯的答案。 – masaers 2012-02-06 06:38:45

0

以上答案都不適用於我的類似問題。 $ 1似乎沒有改變(perl 5.16.3),因此$ hash {$ 1} ++只會計數第一次匹配n次。

爲了獲得每個匹配,foreach需要一個局部變量賦值,然後包含匹配變量。這裏有一個小腳本可以匹配和打印每個(數字)事件。

#!/usr/bin/perl -w                              
use strict; 
use warnings FATAL=>'all'; 

my (%procs); 
while (<>) { 

    foreach my $proc ($_ =~ m/\((\d+)\)/g) { 
     $procs{$proc}++; 
    } 

} 

print join("\n",keys %procs) . "\n"; 

我使用的是這樣的:

pstree -p | perl extract_numbers.pl | xargs -n 1 echo 

(除了在流水線一些相關的過濾器)。任何模式捕獲都應該工作。

相關問題