使用正则表达式解析许可证文件

时间:2018-05-17 14:10:17

标签: regex perl pcre

我想解析一个许可证文件,该文件以某种方式具有这样的内容。

  

COMPONENTS =“A0000 B0000 G0000”

引号必须存在于文件中,以标记包中组件的开始和结束。我已经在regex101.com上测试了组合,但这并没有解决问题

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

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

我需要帮助提取所有这些单独的值。请帮忙。

3 个答案:

答案 0 :(得分:2)

我可能误解了这个问题但是那个简单的

ffmpeg/android/arm

这需要多行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(或任何其他前导关键词),并假设它们彼此无关,因此需要单独存储。

请澄清假设是否错误。

上面的代码创建了哈希

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

其中PACKAGES是一个arrayref,包含该关键字所有行的组件。

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

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

其中[ ... ]是包含来自一行的组件的arrayrefs,它们都存储在一个arrayref中,这是一个键的值。因此,每行的组件都是单独存储的,而不是像前一种情况一样存储在一个arrayref中。

如果在[ ... ]之前还有任何其他单词,则将它们存储为自己的键,并使用自己的arrayref(s)包含来自这些行的数据。

更新以澄清

由于引号可能会或可能不会,因此第一个引号可选=

?

虽然不需要处理尾随的,因为其他数据需要匹配

答案 1 :(得分:2)

由于我的解决方案适合您,我正在发布答案:

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

模式匹配:

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

答案 2 :(得分:1)

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

你的问题的核心是,重复匹配你也匹配前缀文本,显然只能匹配一次。

但是,不是试图让你的正则表达式更复杂,答案是以不同的方式解决问题。

#!/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";
}