我有许多文本文件,其中包含与层次结构相关的字符串。

编辑这是一个示例。这些文件基本上如下所示

HEBV000000000000
HEH11111111  2222222022HCPP      3333        0000 AAA
HET11111  22222222222222
HEH888888  3333333333HCPP      3333        0000 AAA
HET2222  33333333333333333
HEH44444444 55555555HCPP      4444      0000 BBB
HET555555  0066666666666666666
HEE0019000000090
HEBV0120150301429
HEH5588558888 5555000044440000NCPP       164201503010000 HIP
HER9999A 0157000120150303333
HET8888B 0036400120150303333
HEE0044000000040


细分为:

HEB (start of batch1)
HEH (start of group1)
HET (end of group1)
HEH (start of group2)
HET (end of group2)
HEH (start of group3)
HET (end of group3)
HEE (end of batch1)
HEB (start of batch 2)
HEH (start of group1)
HER (start of subgroup1)
HET (end of group1)
HEE (end of batch2)


字符串以几种方式关联:

HEB字符串表示批次的开始。 HEE详细说明了前一批中的HEH,HER和HET记录数。

下一个关系是文档的内容,即HER和HET记录与单个HEH相关。批次(HEB到HEE)可以包含多个HEH-HER-HET组。一批中至少会有一个HEH-HET组;可能有很多。如果存在HER记录,则与该记录之前的HEH及其后的所有HET相关,直到遇到新的HER或HEH。因此,HER和HET记录仅与单个HEH记录相关,但是HEH记录可以与多个HER和HET记录相关联。

任何字符串中都没有链接标识符。这样,唯一可用的关系就是字符串在文件中的位置。 (不是我做的,我无法更改)

我想做的是有一个基于HET记录的输出文件,其外观如下所示,以便我可以将其导入统计数据包中(请注意,我的意思是从每一行打印整个字符串,但为了便于阅读我只是显示字符串的HE *):

HET1 HEH1 HEB FILENAME HEE
HET2 HEH2 HER2 HEB FILENAME HEE
HET3 HEH3 HER3 HEB FILENAME HEE


等等。

我认为它会如何工作的逻辑是:

Read in the file
Get filename and append to HEB records

Then
Look for HEB record and store
Look for HEE record and store
Append HEB and HEE to HEH
  if new HEB is found repeat above until end of file

Then

Look for HEH record and store
Append to HET records until an HEH or HEE record is found
if a new HEH is found, append it to HET records until HEH or HEE is found
repeat until eof

Then

Look for HER record and store
Append to HET records until an HER, HEH or HEE record is found
if a new HER is found, append it to HET records until an HER, HEH or HEE record is found
repeat until eof
save to new file


我认为那会让我进入

HET1 HEH1 HEB FILENAME HEE
HET2 HEH2 HER2 HEB FILENAME HEE
HET3 HEH3 HER3 HEB FILENAME HEE


我以前曾用类似格式的文件问过类似的问题:

Bash: loop through file line by line, find specific string and append to each subsequent line until same string is found



bash & awk: Loop through dir running two separate awk commands on all files and saving in new dir

不幸的是,由于存在多层关系,这些文件更加复杂。这超出了我根据其他问题修改解决方案的能力

码:

for f in *txt
do
    awk '/^AB1/{ab1=$0;next}/^AB2/{print $1, $2, ab1}' "$f" > "new$f"
    awk '{print $1,$2,$3,$4,$5,$6,FILENAME}' "new$f" > "newnew$f"
done


我不知道awk在这里是否是个好主意,或者像Perl或Java之类的东西会更好。正如我在其他问题中提到的那样,我是一名医生,而不是程序员,尽管我可以对代码进行一定的了解(通常会绊倒),但是当我遇到这样的事情时,我发现自己远远超出了我的理解范围。

最佳答案

我认为这会按照您的意愿进行,但是您的描述有点不透明


该程序跟踪最近的HEB和HEH记录以及自上一个HEH或HET以来的所有HER记录的值
我已经使用了输入文件中每行的第一个字段。目前尚不清楚这是否足够,或者您是否需要整行中的数据
每当遇到HET时,输出记录的内容就会保存在数组@records中,但是此时它们缺少HEE信息,因此无法打印
在每个HEE记录中,所有等待输出与当前记录的值一起打印,并且等待列表为空
请注意,我从您自己的示例中略微更改了输入,以允许每个HEH包含多个HET记录,并且每个HET包含多个HER记录
@ARGV = 'f1.txt'行模拟命令行上的参数,就像您输入perl process_data.pl f1.txt一样。您应该在使用代码之前删除此行,并且预期的方法是对参数使用glob模式,以便外壳程序将找到所有相关文件并将其传递给代码




use strict;
use warnings 'all';
use feature 'state';

@ARGV = 'f1.txt';

my ( $heb, $heh, @her );

my @records;

while ( <> ) {

    my ($item) = split;

    die unless my ($type) = $item =~ /^(HE[BHRTE])/;

    state $dispatch = {
        HEB => sub {
            $heb = shift;
            $heh = undef;
            @her = ();
        },
        HEH => sub {
            $heh = shift;
            @her = ();
        },
        HER => sub {
            push @her, shift;
        },
        HET => sub {
            my $het      = shift;
            my $filename = $ARGV;
            push @records, [ $het, $heh, @her, $heb, $filename ];
            @her = ();
        },
        HEE => sub {

            my $hee = shift;

            for my $rec (@records) {
                push @$rec, $hee;
                print "@$rec\n";
            }

            $heb = $heh = undef;
            @her = ();
            @records = ();
        },
    };

    $dispatch->{$type}->($item);
}


输入

HEBV000000000000
HEH11111111  2222222022HCPP      3333        0000 AAA
HET11111  22222222222222
HEH888888  3333333333HCPP      3333        0000 AAA
HET2222  33333333333333333
HEH44444444 55555555HCPP      4444      0000 BBB
HET555555  0066666666666666666
HEE0019000000090
HEBV0120150301429
HEH5588558888 5555000044440000NCPP       164201503010000 HIP
HER9999A 0157000120150303333
HER9999B 0157000120150303333
HET8888B 0036400120150303333
HER9999C 0157000120150303333
HER9999D 0157000120150303333
HET8888B 0036400120150303333
HEE0044000000040


输出

HET11111 HEH11111111 HEBV000000000000 f1.txt HEE0019000000090
HET2222 HEH888888 HEBV000000000000 f1.txt HEE0019000000090
HET555555 HEH44444444 HEBV000000000000 f1.txt HEE0019000000090
HET8888B HEH5588558888 HER9999A HER9999B HEBV0120150301429 f1.txt HEE0044000000040
HET8888B HEH5588558888 HER9999C HER9999D HEBV0120150301429 f1.txt HEE0044000000040

09-25 23:39