Regex 将纯文本数据库解析为数据结构

Regex 将纯文本数据库解析为数据结构,regex,perl,parsing,data-structures,perl-data-structures,Regex,Perl,Parsing,Data Structures,Perl Data Structures,我有一个100MB的纯文本数据库文件,我想解析并转换为数据结构,以便于访问。环境是perl和cygwin。由于我们从第三方接收包含数据的纯文本文件,所以我无法使用任何现有的解析器,如xml或google协议缓冲区 文本文件如下所示 Class=Instance1 parameterA = <val> parameterB = <val> parameterC = <val> ref = Instance2 Class=Instance2 parameterA

我有一个100MB的纯文本数据库文件,我想解析并转换为数据结构,以便于访问。环境是perl和cygwin。由于我们从第三方接收包含数据的纯文本文件,所以我无法使用任何现有的解析器,如xml或google协议缓冲区

文本文件如下所示

Class=Instance1
parameterA = <val>
parameterB = <val>
parameterC = <val>
ref = Instance2

Class=Instance2
parameterA = <val>
parameterB = <val>
parameterC = <val>
Class=Instance1
参数a=
参数b=
参数c=
ref=实例2
类=实例2
参数a=
参数b=
参数c=
该文件包含大量的类变体


解析这个的最佳选项是什么?yacc/lex会帮助我吗?还是我应该编写自己的perl解析器?

这应该可以解决问题。它通过检查第一行自动检测行尾,这里的假设是一条记录被一个空行分隔

在每个记录中,假设键/值对以等号(
=
)连接,可能还有一些空格

这是我的密码:

#!/bin/env perl
use strict;
use warnings;

use Data::Dumper;
use Getopt::Long;

my $db_file;

GetOptions(
    'file=s' => \$db_file,
);

sub detect_line_ending {
    my ($fh) = @_;

    my $line = <$fh>;
    # Rewind to the beginning
    seek($fh, 0, 0);

    my ($ending) = $line =~ m/([\f\n\r]+$)/s;

    return $ending;
}

sub process_chunk {
    my ($chunk, $line_ending) = @_;

    my @lines = split(/$line_ending/, $chunk);

    my $section = {};
    foreach my $line (@lines) {
        my ($key, $value) = split(/[ \t]*=[ \t]*/, $line, 2);
        $section->{$key} = $value;
    }

    return $section;
}

sub read_db_file {
    my ($file) = @_;

    my $data = [];

    open (my $fh, '<', $file) or die $!;
    my $line_ending = detect_line_ending($fh);

    {
        local $/ = $line_ending.$line_ending;

        while (my $chunk = <$fh>) {
            chomp $chunk;

            my $section = process_chunk($chunk, $line_ending);
            push @$data, $section;
        }
    }
    close $fh;

    return $data;
}

print Dumper read_db_file($db_file);
#/bin/env perl
严格使用;
使用警告;
使用数据::转储程序;
使用Getopt::Long;
我的$db_文件;
获取选项(
'file=s'=>\$db\u文件,
);
子检测线结束{
我的($fh)=@;
我的$line=;
#倒带到开头
寻求(fh,0,0);
my($ending)=$line=~m/([\f\n\r]+$)/s;
返回$end;
}
子进程{
我的($chunk,$line_结尾)=@;
my@lines=split(/$line\u end/,$chunk);
我的$section={};
foreach my$行(@行){
my($key,$value)=拆分(/[\t]*=[\t]*/,$line,2);
$section->{$key}=$value;
}
返回$section;
}
子读取数据库文件{
我的($file)=@;
我的$data=[];
打开(我的$fh,这是你想要的吗

#!/usr/bin/perl
use Data::Dumper;
use Modern::Perl;

my %classes;
my $current;
while(<DATA>) {
    chomp;
    if (/^Class\s*=\s*(\w+)/) {
        $classes{$1} = {};
        $current = $1;
    } elsif (/^(\w+)\s*=\s*(.+)$/) {
        $classes{$current}{$1} = $2;
    }
}
say Dumper\%classes;
!/usr/bin/perl
使用数据::转储程序;
使用Modern::Perl;
我的%班级;
我的$current;
while(){
咀嚼;
如果(/^Class\s*=\s*(\w+/){
$classes{$1}={};
$current=$1;
}elsif(/^(\w+)\s*=\s*(.+)$/){
$classes{$current}{$1}=$2;
}
}
说Dumper\%类;
输出:

$VAR1 = {
          'Instance2' => {
                         'parameterC' => '<val>',
                         'parameterB' => '<val>',
                         'parameterA' => '<val>'
                       },
          'Instance1' => {
                         'parameterC' => '<val>',
                         'ref' => 'Instance2',
                         'parameterB' => '<val>',
                         'parameterA' => '<val>'
                       }
        };
$VAR1={
'实例2'=>{
'参数c'=>'',
'参数B'=>'',
'参数'=>''
},
'实例1'=>{
'参数c'=>'',
'ref'=>'Instance2',
'参数B'=>'',
'参数'=>''
}
};

您的预期输出是什么?“是的,您已经使用YACC/LEX自定义解析文件,并且在中构建了regecpearl@BhargavModi:regec in pearl???@serenesat我应该发布一个演示答案,但这只是一个想法吗?@BhargavModi:pearl???如果你的意思是
perl
,那么还是拼写错误。所以你建议我自己写PAR呃!