2010-06-29 116 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*,确保正则表达式总是匹配,所以没有项目被滤除。