2017-06-19 58 views
3

我想一个参数报关行的参数名称相匹配,如下面:Perl非贪婪匹配 - 是“?”字符使用正确吗?

parameter BWIDTH = 32;

使用Perl的正则表达式为:

$line =~ /(\w+)\s*=/

其中参数名称,BWIDTH ,被捕获到$1。我遇到的大多数参数都以这样一种方式声明,即名称在等号"="之前,这就是正则表达式设计为"="/(\w+)\s*=/)的原因。

但也有在参数声明的特殊情况:

parameter reg [31:0] PORT_WIDTH [BWIDTH-1:0] = 32;

在这种情况下,我想捕捉参数名称为PORT_WIDTH。修改正则表达式以匹配此实例不会成功捕获PORT_WIDTH,但它确实捕获了BWIDTH的罚款。

$line =~ /(\w+)(\s*\[.*?\])*\s*=/

其中(\s*\[.*?\])*匹配reg [31:0] PORT_WIDTH [BWIDTH-1:0]这是贪婪匹配。

我很困惑,为什么元字符?不停止贪婪的匹配?我应该如何修改正则表达式?

+0

重新 “* Perl的非贪婪匹配 - 是的‘’正确使用的字符*?”,如果你使用它,只能作为?一个优化,我会争辩说不。 – ikegami

回答

3

更换.*?[^][]*匹配比][其他0+字符:

/(\w+)(\s*\[[^][]*])*\s*=/ 
      ^^^^^^ 

您还可以,如果你不使用该值变成第二个捕获组到非捕获一个。

图案的详细资料

  • (\w+) - 第1组:一个或多个单词字符
  • (\s*\[[^][]*])* - 捕获组(添加?:(后,使其成为非捕获)零个或多个的:
    • \s* - 0+空格
    • \[ - 字面[
    • [^][]* - 一个否定的字符类匹配比]其他零个或多个字符和[
    • ] - 字面]
  • \s* - 零个或多个空格
  • = - 一个等号。
3

贪婪与非贪婪影响,其中一场比赛结束,但它仍然开始尽早。基本上,贪婪的匹配是最长可能的匹配,而非贪婪是最短的。但不贪心仍然是最左边,而不是最右边。

为了得到你想要的东西,我会用什么,我想匹配一个更明确的说明:/(\w+)(\s*\[[^]]*\])?\s*=/在英语中,这是一个字(\w+),任选随后在方括号一些文字((\s*\[[^]]*\])?),然后可选空白和等号。请注意,我使用的是否定字符类([^]]),而不是非括号内的括号内的非贪婪匹配 - IMO,否定字符类通常是比非贪婪匹配更好的选项。

结果与此正则表达式:

$ perl -E '$x = q(parameter reg [31:0] PORT_WIDTH [BWIDTH-1:0] = 32;); $x =~ /(\w+)(:?\s*\[[^]]*\])?\s*=/; say $1;' 
PORT_WIDTH 
$ perl -E '$x = q(parameter BWIDTH = 32;); $x =~ /:?(\w+)(\s*\[[^]]*\])?\s*=/; say $1;' 
BWIDTH 
+0

谢谢你对贪婪的最左边行为的解释。这非常有用 –

1

你必须提供给你,你是选择不使用信息。你知道你想要解析的每个语句的基本结构。这些声明包含强制性和可选部分。所以,把你的信息放在比赛中。例如:

#!/usr/bin/env perl 

use strict; 
use warnings; 

my $stuff_in_square_brackets = qr{ \[ [^\]]+ \] }x; 

my $re = qr{ 
    ^
    parameter \s+ 
    (?: reg \s+)? 
    (?: $stuff_in_square_brackets \s+)? 
    (\w+) \s+ 
    (?: $stuff_in_square_brackets \s+)? 
    = \s+ 
    (\w+) ; 
    $ 
}x; 

while (my $line = <DATA>) { 
    if (my($p, $v) = ($line =~ $re)) { 
     print "'$p' = '$v'\n"; 
    } 
} 

__DATA__ 
parameter BWIDTH = 32; 
parameter reg [31:0] PORT_WIDTH [BWIDTH-1:0] = 32; 

输出:

'BWIDTH' = '32' 
'PORT_WIDTH' = '32'