代码之家  ›  专栏  ›  技术社区  ›  Pranay Nanda

使用regex解析许可证文件

  •  2
  • Pranay Nanda  · 技术社区  · 7 年前

    我想解析一个许可证文件,它有这样的内容。

    组件=“A0000 B0000 G0000”

    文件中必须有引号,用于标记包中组件的开始和结束。我已经在手机上测试过了 regex101.com 但这并不能解决问题

    正则表达式 ("?(?<components>\w+)*\s?"?) 用于字符串“A0000 B0000 G0000”,并返回我需要的组件的各个值:A0000、B0000等等

    但当我测试的时候 (COMPONENTS|PACKAGES)=("?(?<components>\w+)\s?"?) ,块无法返回这些值,只返回第一个值,即A0000。

    我需要帮助提取所有这些个人价值观。请帮忙。

    3 回复  |  直到 7 年前
        1
  •  2
  •   Wiktor Stribiżew    7 年前

    由于我的解决方案对您有效,我发布了一个答案:

    (?:\G(?!^)\s+|(?:COMPONENTS|PACKAGES)=")\K[^\s"]+
    

    模式匹配:

    • (?:\G(?!^)\s+|(?:COMPONENTS|PACKAGES)=") -两种选择之一:
    • \G(?!^)\s+ -上一场比赛结束( \G 匹配行/字符串的开头或上一个匹配的结尾,因此 (?!^) “减去”字符串起始位置)和1+空格
    • | -或者
    • (?:COMPONENTS|PACKAGES)= -要么 COMPONENTS= PACKAGES=
    • \K -匹配重置运算符(丢弃当前匹配的文本)
    • [^\s"]+ -除空格和双引号外的1个或多个字符。
        2
  •  2
  •   zdim    7 年前

    我可能误解了这个问题,但简单的问题呢

    my %result;
    while (<$fh>) {
        my ($type, $components) = /(\w+)\s*=\s*"([^"]+)/;
        push @{$result{$type}}, split ' ', $components;      # all in one arrayref
        #push @{$result{$type}}, [ split ' ', $components ]; # or as separate ones
    }
    

    这需要多条带有 COMPONENTS 和/或 PACKAGES (或任何其他主要关键字),并假设它们彼此无关,因此需要单独存储。

    请澄清假设是否错误。

    上面的代码创建了散列

    (
        COMPONENTS => [ 'A0000', 'B0000', 'G0000', ... ],
        PACKAGES   => [ ... ],
    )
    

    哪里 [ ... ] 是包含该关键字所有行的组件的arrayref。

    或者,如果使用代码中注释掉的行而不是上面的行,

    (
        COMPONENTS => [ ['A0000', 'B0000', 'G0000'], [ ... ], ... ],
        PACKAGES   => [ [ ... ], [ ... ], ... ],
    )
    

    哪里 [ ... ] arrayref包含一行中的组件,这些组件都存储在arrayref中,arrayref是键的值。因此,这里每一行的组件都是单独存储的,而不是像前一种情况那样全部存储在一个arrayref中。

    如果之前还有其他的话 = 它们作为自己的密钥存储,并带有自己的arrayref和来自这些行的数据。


    使现代化 澄清

    因为引号可能存在,也可能不存在,所以第一个引号是可选的 ?

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

    而后面的一个不需要处理,因为其余的数据需要匹配

        3
  •  1
  •   Borodin    7 年前

    我将在这里提出一种不同的方法。你的正则表达式模式越来越复杂,这不是个好主意。

    问题的核心是,要进行重复匹配,您也在匹配前缀文本,显然,这只能匹配一次。

    但与其试图让你的正则表达式模式变得更加复杂,答案是以不同的方式处理这个问题。

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    use Data::Dumper;
    
    my %conf = do { local $/; <DATA> } =~ m/ (\w+) =" ([^"]+) " /xg; 
    print Dumper \%conf; 
    
    __DATA__
    COMPONENTS="A0000 B0000 G0000"
    PACKAGES="C0000 D0000 E0000"
    

    这将创建一个数据结构。

    $VAR1 = {
              'COMPONENTS' => 'A0000 B0000 G0000',
              'PACKAGES' => 'C0000 D0000 E0000'
            };
    

    如果你想把这些值分开。

    $_ = [split] for values %conf;
    print Dumper \%conf; 
    

    这在功能上等同于此。

    foreach my $key ( keys %conf ) {
    
      #split the value on whitespace.
      my @stuff = split ' ', $conf{$key};
    
      #replace it with your array. 
      $conf{$key} = \@stuff;
    

    }

    产生

    $VAR1 = {
              'PACKAGES' => [
                              'C0000',
                              'D0000',
                              'E0000'
                            ],
              'COMPONENTS' => [
                                'A0000',
                                'B0000',
                                'G0000'
                              ]
            };
    

    现在你可以写这个了。

    foreach my $value ( @{$conf{'COMPONENTS'}} ) { 
        print $value,"\n";
    }