读取大文件并输出与多个参数匹配的部分

win*_*ndm 6 perl awk

我很少需要处理脚本,所以我反对对这个问题缺乏了解.

我有一个文件> 500mb的文本,这是很好的切片,但我知道里面有5到10个"坏"部分.部分中的数据可以很容易地被人类评估,我不知道如何在程序中进行.

我选择了一个已知的好价值#Field MyField- 但是如果没有出现这个值,那就#FIELD LOCATION出错了.

文件中两个部分的示例如下所示.第一个是"坏",第二个是"好".

#START Descriptor
#FIELD LOCATION="http://path.to/file/here&Value=FOO&OtherValue=BLAH"
#FIELD AnythingElse
#FIELD MyField="BAR"
#END
#START Descriptor
#FIELD LOCATION="http://path.to/file/here&Value=BAR&OtherValue=BLAH"
#FIELD AnythingElse
#FIELD MyField="BAR"
#END
Run Code Online (Sandbox Code Playgroud)
  1. 部分以逻辑方式开始和结束,使用#START#END

  2. 如果#FIELD LOCATION不存在,请转到下一部分

  3. 如果#FIELD MyField="BAR"#FIELD LOCATION不包含BAR,则将此部分中的所有行打印到新文件.

  4. 注意 - 澄清#FIELD MyField="BAR"- 这是我通过在构建此文件时获取有关数据的其他信息而放入的检查值(在我的情况下,它是一个语言指示符,例如EN或DE.所以它实际上是#FIELD MyField="EN" 任何其他值在此字段中将被忽略,这不是符合我的条件的记录.

我相信这可以在Awk或Perl中完成,我可以做非常简单的单行,但这超出了我的技能.

TLP*_*TLP 2

你可以做如下的事情。这只是一个草稿,但它适用于您的示例数据。使用触发器运算符查找记录的开头和结尾。使用哈希来存储字段值,使用数组来存储记录。

我只是检查该值是否在位置字符串中,您可能希望通过确保它位于正确的位置或正确的大小写来进一步缩小检查范围。

use strict;
use warnings;

my @record;
my %f;
while(<DATA>) {
    if (/^#START / .. /^#END */) {
        if (/^#START /) {
            @record = (); # reset
            %f = ();
        }
        push @record, $_;
        if (/^#END */) { # check and print
            if ($f{'LOCATION'} !~ /$f{'MyField'}/) {
                print @record; 
            }
        } else {         # add fields to hash
            if (/^#FIELD (.+)/) {
                            # use split with limit of 2 fields
                my ($key, $val) = split /=/, $1, 2;
                next unless $val; # no empty values
                $val =~ s/^"|"$//g; # strip quotes
                $f{$key} = $val;
            }
        }
    }
}

__DATA__
#START Descriptor
#FIELD LOCATION="http://path.to/file/here&Value=FOO&OtherValue=BLAH"
#FIELD AnythingElse
#FIELD MyField="BAR"
#END
#START Descriptor
#FIELD LOCATION=http://path.to/file/here&Value=BAR&OtherValue=BLAH"
#FIELD AnythingElse
#FIELD MyField="BAR"
#END
Run Code Online (Sandbox Code Playgroud)