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