我正在尝试匹配参数声明行的参数名称,如下所示:
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 :(得分:2)
将.*?
替换为[^][]*
,以匹配]
和[
以外的0 +字符:
/(\w+)(\s*\[[^][]*])*\s*=/
^^^^^^
如果您没有使用该值,您也可以将第二个捕获组变为非捕获组。
模式详情:
(\w+)
- 第1组:一个或多个单词字符(\s*\[[^][]*])*
- 一个捕获组(在?:
之后添加(
以使其无法捕获)零次或多次出现:
\s*
- 0+ whitespaces \[
- 文字[
[^][]*
- 与]
和[
以外的零个或多个字符匹配的否定字符类]
- 文字]
\s*
- 零个或多个空格=
- 等号。答案 1 :(得分:2)
贪婪与非贪婪会影响匹配结束的位置,但仍会尽早启动。基本上,贪婪的匹配是最左边最长的匹配,而非贪婪是最左边的。但非贪婪仍然是最左边的,而不是最右边的。
为了得到你想要的东西,我会更明确地描述我想要匹配的东西:/(\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
答案 2 :(得分: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'