Ключ заключается в том, чтобы анализировать один блок за раз и сопоставлять все соответствующие данные одновременно. См. qr
в perldoc perlp и $ / в perldoc perlvar .
Учитывая тот факт, что вы также хотели поместить информацию в структуру данных, которая позволила бы вам запрашивать информацию и манипулировать ею, вот один из последних вариантов. Приведенный ниже код использует возможность SQLite для создания баз данных в памяти. Возможно, вы захотите разделить функциональность на два сценария: один для анализа и хранения данных, а другой для выполнения любых необходимых вам манипуляций. На самом деле, в SQL можно сделать все необходимые манипуляции.
#!/usr/bin/perl
use v5.010;
use strict; use warnings;
use DBI;
my $dbh = get_dbh();
my $header_pattern = qr{
History[ ]for: [ ](?<filename>[^\n]+) \n
Description: [ ](?<description>[^\n]+) \n
Locked[ ]by: [ ]?(?<lockedby>[^\n]*) \n
Status: [ ](?<status>.[^\n]+) \n
}x;
my $revision_pattern = qr{-+\n
Revision: [ ](?<revision>\d+) [ ]
View: [ ](?<view>.+) [ ]
Branch[ ]Revision: [ ](?<branch_revision>[^\n]+) \n
Author: [ ](?<author>.+) [ ]
Date: [ ](?<revdate>[^\n]+) \n
(?<summary>.*) \n
}x;
local $/ = '=' x 77 . "\n";
while ( my $entry = <>) {
if ( $entry =~ $header_pattern ) {
my %file = %+;
$dbh->do(sprintf(
q{INSERT INTO files (%s) VALUES (%s)},
join(',', keys %file),
join(',', ('?') x keys %file),
), {}, values %file );
while ( $entry =~ /$revision_pattern/g ) {
my %rev = %+;
$dbh->do(sprintf(
q{INSERT INTO revisions (%s) VALUES (%s)},
join(',', filename => keys %rev),
join(',', ('?') x (1 + keys %rev)),
), {}, $file{filename}, values %rev );
}
}
}
my $revs = $dbh->selectall_arrayref(
q{SELECT * FROM revisions JOIN files
ON files.filename = revisions.filename},
{ Slice => {} }
);
use Data::Dumper;
print Dumper $revs;
sub get_dbh {
my $dbh = DBI->connect(
'dbi:SQLite:dbname=:memory:', undef, undef,
{ RaiseError => 1, AutoCommit => 1 }
);
$dbh->do(q{PRAGMA foreign_keys = ON});
$dbh->do(q{CREATE TABLE files (
filename VARCHAR PRIMARY KEY,
description VARCHAR,
lockedby VARCHAR,
status VARCHAR
)});
$dbh->do(q{CREATE TABLE revisions (
filename VARCHAR,
revision VARCHAR,
view VARCHAR,
branch_revision VARCHAR,
author VARCHAR,
revdate VARCHAR,
summary VARCHAR,
CONSTRAINT pk_revisions PRIMARY KEY (filename, revision),
CONSTRAINT fk_revisions_files FOREIGN KEY (filename)
REFERENCES files(filename)
)});
return $dbh;
}
Выход:
C:\Temp> y.pl test.txt
$VAR1 = [
{
'status' => 'Current',
'revdate' => '3/22/08 11:16:16 AM CST',
'author' => 'John Smith',
'description' => 'Some files',
'revision' => '1',
'filename' => 'main.h',
'summary' => 'Main header',
'view' => 'The View Name',
'branch_revision' => '1.0',
'lockedby' => ''
},
{
'status' => 'Current',
'revdate' => '3/22/08 1:55:55 PM CST',
'author' => 'Jane Doe',
'description' => 'Some files',
'revision' => '2',
'filename' => 'main.c',
'summary' => 'Made an update.',
'view' => 'The View Name',
'branch_revision' => '1.1',
'lockedby' => ''
},
{
'status' => 'Current',
'revdate' => '3/22/08 11:16:16 AM CST',
'author' => 'John Smith',
'description' => 'Some files',
'revision' => '1',
'filename' => 'main.c',
'summary' => 'Initial revision',
'view' => 'The View Name',
'branch_revision' => '1.0',
'lockedby' => ''
}
];