2010-06-29 111 views
4

我有一個很長的正則表達式,它將文本文件解析爲各種匹配變量。如何迭代Perl中的正則表達式匹配變量?

爲了健壯性,匹配變量可能包含空格。我想通過迭代匹配變量來以系統方式刪除空白。

例如,我有匹配變量$2$14包含一些空格。

我可以這樣做:

my @columns = my ($serNum, $helixID, $initResName, $initChainID, 
$initSeqNum, $initIcode, $endResName, $endChainID, $endSeqNum, 
$endICode, $helixClass, $comment, $length) = 
($2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14); 

### Remove whitespace      
foreach my $element (0..$#columns) { 
    $columns[$element] =~ s/^\s+//; 
    $columns[$element] =~ s/\s+$//; 
} 

但是,這不僅能消除在@column中的元素的白色空間,離開正確命名標量,$serNum$helixID等不變。

有沒有辦法在每個匹配變量中刪除空白空間,然後再將它們複製到更有名的標量之前,還是有一種方法可以遍歷這些熟悉的標量並從中刪除空白?

我推測可能有一些方法可以用引用來做到這一點。

+2

請注意,如果您只是將匹配操作的結果指定給您的命名變量,那麼您不必引用'$ 2,$ 3,...'名稱('m //'將返回在我的($ serNum,...)=($ foo =〜m/pattern /);' – Ether 2010-06-29 19:32:00

+0

謝謝。這是一個有用的觀點。 – EMiller 2010-06-29 19:39:33

回答

4

可以先存放在數組中的匹配變量,然後使用地圖剝離空白:

my @matches = ($2, $3, $4, ...); 

my ($serNum, $helixID, ...) 
    = map { (my $v = $_) =~ s/^\s+|\s+$//g; $v } @matches; 
+0

eugene,這真是太棒了!感謝您提供強大的地圖。 雖然你是對的,我可以修改正則表達式來捕獲數據W/O空白,我想使用。元字符以避免對我要捕捉的角色加以限制。捕獲所有內容似乎比較簡單,只是刪除前後的空白,而不是列出所有可能性,包括可能正確包含空白的數據。 – EMiller 2010-06-29 19:31:39

+1

或'my($ serNum,$ helixID,...)= grep {s#^ \ s * | \ s * $ ## g} @matches;'爲了變化。 – Zaid 2010-06-30 06:50:00

2

讓人耳目一新看到細節的問題,一個良好的水平!它使社區能夠以更好的方式解決問題。

我會做的是從'精心命名'的元素數組遷移到散列。這是更清潔的,並有可能減少代碼中所需的變量數量。

my @matches = $data =~ m{$regex}; # Populates @matches with ($1, $2, $3, ..) 
my @labels = qw/serNum helixID initResName .../; # Create labels 

my %record;         # Initialize hash 
@record{@labels} = grep { s!^\s*|\s*$!!g } # Strips out leading/trailing spaces 
        @matches[1..$#matches]; # Populate %record with array slice 
              # Array slice of @matches needed to 
              # ignore the $1 

# Now data can be accessed as follows: 
print $record{helixID};      # Prints the helix ID in the record 

grep部分可能需要一些解釋。這是避免必須在map調用中詞彙複製每個字符串的奇特方式。

就其性質而言,grep過濾器陣列。這就是爲什麼空白剝離正則表達式不得不從\s+修改爲\s*,確保正則表達式總是匹配,所以沒有項目被濾除。