regex - Perl Regex 试图读取我评论中的宏

标签 regex perl

我有一个程序可以将命令嵌入到 XML 文件、属性文件和其他文件的注释中。我识别三种不同类型的评论:

  • Perl 和 Shell 脚本注释(以 # 开头的行)
  • Python 和 Java 风格的注释(以 // 开头的行)
  • XML 样式注释(行以 <-- 开始并以 --> 结束

我有一个 IF 宏,如果一个属性被设置为特定值,我将注释掉以下所有行,直到我得到一个嵌入的 `ENDIF 或不管它们。

这是一个例子:

# IF: MACHINE = SERVER
# SERVER_PORT = 1022
# ENDIF:

这是一个类似的 XML 格式示例:

<!-- IF: NOT MACHINE SERVER -->
    <server>foo.vegicorp.com</server>
<!-- ENDIF: -->

我需要捕获的内容:

   1. 2.  3.   4.    5.    6.   7.
   |  |   |    |     |     |    |
<!-- IF: NOT MACHINE =  SERVER -->
  1. 评论的开头(必须在文件的第一列)
  2. 字符串 IF:
  3. 可选字符串 NOT (如果存在,捕获 #1)
  4. 属性名称(捕获 #2)
  5. 一个可选等号
  6. 属性值(捕获#3)
  7. 如果这是 XML 行,则为可选的结束注释

不知何故,我根本没有正确选择正则表达式。这是我拥有的:

$if_line_re = qr@^(?:<\!--|#|//)\s*IF:\s+(?:(NOT)\s+)?(\S+)\s+(?:=\s)?(\S+)(?:\s*-->)?@i;

这是我的模板文件:

# Macro: machine_type choice
# Q: WHat type of machine is this?
# C: Server:SERVER
# C: Client:CLIENT
# C: A type of toaster:TOASTER

# Macro: QUESTION integer
# Q: What is an example of a number

question=%QUESTION%

machine type = %machine_type%

# IF: Machine = SERVER
machine = server

# ENDIF:

# IF: NOT MACHINE = SERVER

Machine = Toaster? Maybe Client?

# ENDIF: 

# IF: Machine = Toaster
machine = Definitely a toaster!

# ENDIF:

模板的填写方式如下:

# Macro: machine_type choice
# Q: WHat type of machine is this?
# C: Server:SERVER
# C: Client:CLIENT
# C: A type of toaster:TOASTER

# Macro: QUESTION integer
# Q: What is an example of a number

question=34

machine type = TOASTER

# IF: Machine = SERVER -->
# machine = server
# 
# ENDIF:

# IF: NOT MACHINE = SERVER

Machine = Toaster? Maybe Client?

# ENDIF: 

# IF: Machine = Toaster
# machine = Definitely a toaster!
# 
# ENDIF:

我添加了一些调试行来显示发生了什么:

DEBUG: if ( 0 and SERVER eq  ) { at ./autoconfig.pl line 1048, <$template_fh> line 32.
DEBUG: if ( not 0 and SERVER ne  ) { at ./autoconfig.pl line 1063, <$template_fh> line 32.
DEBUG: if ( 0 and SERVER eq  ) { at ./autoconfig.pl line 1048, <$template_fh> line 32.
DEBUG: if ( not 0 and SERVER ne  ) { at ./autoconfig.pl line 1063, <$template_fh> line 32.
DEBUG: if ( 1 and SERVER eq  ) { at ./autoconfig.pl line 1048, <$template_fh> line 32.
DEBUG: if ( not 1 and SERVER ne  ) { at ./autoconfig.pl line 1063, <$template_fh> line 32.
DEBUG: if ( 1 and SERVER eq  ) { at ./autoconfig.pl line 1048, <$template_fh> line 32.
DEBUG: if ( not 1 and SERVER ne  ) { at ./autoconfig.pl line 1063, <$template_fh> line 32.
DEBUG: if ( 1 and SERVER eq  ) { at ./autoconfig.pl line 1048, <$template_fh> line 32.
DEBUG: if ( not 1 and SERVER ne  ) { at ./autoconfig.pl line 1063, <$template_fh> line 32.
DEBUG: if ( 0 and Toaster eq  ) { at ./autoconfig.pl line 1048, <$template_fh> line 32.
DEBUG: if ( not 0 and Toaster ne  ) { at ./autoconfig.pl line 1063, <$template_fh> line 32.
DEBUG: if ( 0 and Toaster eq  ) { at ./autoconfig.pl line 1048, <$template_fh> line 32.
DEBUG: if ( not 0 and Toaster ne  ) { at ./autoconfig.pl line 1063, <$template_fh> line 32.

如您所见,我与属性匹配的值未被提取。我的正则表达式匹配该行,但没有捕获属性的值。这是代码:

    elsif ( $line =~ IF_LINE ) {
    my $negation = $1;
    my $parameter = uc $2;
    my $value = $3;
    my $if_clause;
    if ( $negation ) {
        $if_clause = If->new( $parameter, $value, 1 );
    } else {
        $if_clause = If->new( $parameter, $value, 0 );
    }
    push @macro_list, $if_clause;

最佳答案

我将“一个或多个”量词添加到 (?:=\s),结果是 (?:=\s+):

$if_line_re = qr@^(?:<\!--|#|//)\s*IF:\s+(?:(NOT)\s+)?(\S+)\s+(?:=\s+)?(\S+)(?:\s*-->)?@i;

现在我得到:

MATCH 1
1.  [9-12]  `NOT`
2.  [13-20] `MACHINE`
3.  [23-29] `SERVER`

关于regex - Perl Regex 试图读取我评论中的宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24287150/

相关文章:

python - 如何将正则表达式从 perl 转换为 python

c# - C# MVC 4 应用程序中的电子邮件地址验证 : with or without using Regex

javascript - 正则表达式查找 url 是否有文件名尾部

perl - OO-Perl 别名类属性

perl - 为什么 File::Slurp 在应该返回一个列表时返回一个标量?

perl - 使用 Spreadsheet::WriteExcel 读取文件并将段写入 Excel

perl - 你能扩展 pack() 来处理自定义的可变长度字段吗?

javascript - 如何使用正则表达式匹配高值 unicode 字符?

Perl + 多个 ALRM 信号的可能性

javascript - 匹配多个值并将重复值替换为一个值