Разбор файла лицензии с помощью регулярного выражения - PullRequest
0 голосов
/ 17 мая 2018

Я хочу разобрать файл лицензии, который каким-то образом имеет такое содержимое.

COMPONENTS = "A0000 B0000 G0000"

Кавычки обязательно присутствуют в файле для обозначения начала и конца компонентов в пакете.Я протестировал комбинации на regex101.com , но это не решает проблему

Регулярное выражение ("?(?<components>\w+)*\s?"?) работает для строки "A0000 B0000 G0000" и возвращает мне отдельные значения компонентов, которыеМне нужно: A0000, B0000 и т. Д.

Но когда я проверяю (COMPONENTS|PACKAGES)=("?(?<components>\w+)\s?"?), блок не может вернуть эти значения и возвращает только первое, которое является A0000.

Мне нужна помощь сизвлекая все эти индивидуальные ценности.Пожалуйста, помогите.

Ответы [ 3 ]

0 голосов
/ 17 мая 2018

Возможно, я неправильно понимаю проблему, но как насчет простого

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   => [ ... ],
)

, где [ ... ] - это ссылка на массив со всеми строками для этого ключевого слова..

Или, если закомментированная строка в коде используется вместо строки над ней,

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

, где [ ... ] - это массивы с компонентами из строки, которыевсе хранится в arrayref, который является значением для ключа.Таким образом, здесь компоненты для каждой строки хранятся отдельно, а не все находятся в одном arrayref, как в предыдущем случае.

Если есть какие-либо другие слова до =, они сохраняются как свои собственные ключи со своими собственнымиarrayref (s) с данными из этих строк.


Обновление до пояснений

Поскольку кавычки могут быть или не быть, сделайте первый необязательным с ?

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

, в то время как завершающий не нужно обрабатывать, так как остальные данные должны быть сопоставлены

0 голосов
/ 22 мая 2018

Поскольку мое решение сработало для вас, я публикую ответ:

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

Шаблон соответствует:

  • (?:\G(?!^)\s+|(?:COMPONENTS|PACKAGES)=") - любой из двух вариантов:
  • \G(?!^)\s+ - конец предыдущего соответствия (\G соответствует либо началу строки / строки, либо концу предыдущего соответствия, поэтому (?!^) "вычитает" начало позиции строки) и 1+пробелы
  • | - или
  • (?:COMPONENTS|PACKAGES)= - либо COMPONENTS=, либо PACKAGES=
  • \K - оператор сброса соответствия (отбрасывает текущий сопоставленный текст)
  • [^\s"]+ - 1 или более символов, кроме пробелов и двойных кавычек.
0 голосов
/ 17 мая 2018

Я собираюсь предложить другой подход здесь.Ваш шаблон регулярных выражений становится сложным, и это не очень хорошая идея.

Суть вашей проблемы в том, что для повторения совпадений вы также сопоставляете текст префикса, и, очевидно, это может совпадать только один раз.

Но вместо того, чтобы пытаться создать шаблон регулярного выраженияеще сложнее, ответ заключается в том, чтобы по-другому подходить к проблеме.

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