2017-06-19 27 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'