Perl:如何整理所提到的所有数据匹配条件

时间:2015-12-22 05:53:40

标签: perl file sorting

我希望从下面的数据中找出一些参数。

例如,如果我只想采用第4列PPST和第5列VDDIFF,如何编写计数器以获取文件中包含PPST和VDDIFF的所有数据?

如果一个文件有十个设备,我怎样才能获得所有十个设备的数据?

我的代码如下,但只需要一次。

单个文件中3个设备数据的示例:

Device#: 12
Number     Site  Result   Test Name                 Pin            Channel     Low            Measured       High           Force        Loc
0           1    PASS     PPST                      VDDIFF         5         -500.0000 uA   3.8867 uA      1.0000 mA      300.0000 mV    0         
1           1    PASS     PPST                      VDDSE          6         -500.0000 uA   19.2512 uA     1.0000 mA      300.0000 mV    0         
2           1    PASS     PPST                      VDDPLL         7         -500.0000 uA   15.6106 uA     1.0000 mA      300.0000 mV    0         
3           1    PASS     PPST                      VDDIO          4         -500.0000 uA   19.4656 uA     1.0000 mA      300.0000 mV    0         
4           1    PASS     Cont2gnd                  CPUC0          21        -1.0000 V      -432.2093 mV   -200.0000 mV   -100.0000 uA   0         
5           1    PASS     Cont2gnd                  CPUT0          4         -1.0000 V      -432.2228 mV   -200.0000 mV   -100.0000 uA   0        
Device#: 50
Number     Site  Result   Test Name                 Pin            Channel     Low            Measured       High           Force        Loc
0           1    PASS     PPST                      VDDIFF         5         -500.0000 uA   3.6867 uA      1.0000 mA      300.0000 mV    0         
1           1    PASS     PPST                      VDDSE          6         -500.0000 uA   19.2512 uA     1.0000 mA      300.0000 mV    0         
2           1    PASS     PPST                      VDDPLL         7         -500.0000 uA   15.6106 uA     1.0000 mA      300.0000 mV    0         
3           1    PASS     PPST                      VDDIO          4         -500.0000 uA   19.4656 uA     1.0000 mA      300.0000 mV    0         
4           1    PASS     Cont2gnd                  CPUC0          21        -1.0000 V      -432.2093 mV   -200.0000 mV   -100.0000 uA   0         
5           1    PASS     Cont2gnd                  CPUT0          4         -1.0000 V      -432.2228 mV   -200.0000 mV   -100.0000 uA   0     
Device#: 51
Number     Site  Result   Test Name                 Pin            Channel     Low            Measured       High           Force        Loc
0           1    PASS     PPST                      VDDIFF         5         -500.0000 uA   3.5867 uA      1.0000 mA      300.0000 mV    0         
1           1    PASS     PPST                      VDDSE          6         -500.0000 uA   19.2512 uA     1.0000 mA      300.0000 mV    0         
2           1    PASS     PPST                      VDDPLL         7         -500.0000 uA   15.6106 uA     1.0000 mA      300.0000 mV    0         
3           1    PASS     PPST                      VDDIO          4         -500.0000 uA   19.4656 uA     1.0000 mA      300.0000 mV    0         
4           1    PASS     Cont2gnd                  CPUC0          21        -1.0000 V      -432.2093 mV   -200.0000 mV   -100.0000 uA   0         
5           1    PASS     Cont2gnd                  CPUT0          4         -1.0000 V      -432.2228 mV   -200.0000 mV   -100.0000 uA   0     

Perl源代码

open( OUT, ">$outfile" );
open( INF, "$infile1" ) || die( " cannot open input file  \n" );

$count = 0;
$Anam  = 'VDDIFF';
$Nnam  = 'PPST';

printf OUT ( "Unit#  Test_Name   Pin_Name    Measure_Data; \n" );

#while ($line1 ne "")
while ( <INF> ) {

    @temp1 = split( /\s+/, $_ );    #($checkR1 eq "R1")

    if ( $temp1[2] eq "1" ) {       # site =1  on datalog

        print "1 $Nnam $Anam\n";

        $Tnam = "$temp1[4]";        # test name
        $Pnam = "$temp1[5]";        # Pin name

        print "$Tnam $Pnam \n";
        print "\n";

        if ( ( $Pnam eq $Anam ) & ( $Tnam eq $Nnam ) ) {
            $count = $count + 1;
        }
        else {
            $count = 1;
        }

        $Anam = $Pnam;              # save as previous Pnam
        $Nnam = $Tnam;              # save as previous Tnam
        $Mval = "$temp1[9]";
        $Unum = "$temp1[10]";

        printf OUT ( "$count         $Tnam               $Pnam           $Mval $Unum\n" );
    }
    else {
        printf OUT "$_\n";
    }
}

close( INF ) || die "cannot close file1 !!";
close( OUT );

print "all done\n";

预期输出

Unit#      Test_Name       Pin_Name        Measure_Data;
 12        PPST            VDDIFF          3.8867 uA
 50        PPST            VDDIFF          3.6867 uA
 51        PPST            VDDIFF          3.5867 uA

2 个答案:

答案 0 :(得分:1)

你好像写了很多不必要的代码。我猜你已经采取了别人的程序来处理相同的输入文件,并试图为了你自己的目的修改它。在让别人为你工作之前,你应该认真努力解决自己的问题

这个程序做我认为你想要的。它期望输入文件的路径作为命令行上的参数,并将输出发送到STDOUT,可以使用shell将其重定向到任何地方

如果您将此源保存在ppst_vddiff.pl中,那么您的命令行应该类似于

ppst_vddiff.pl infile > outfile

Perl代码

#!/usr/bin/env perl

use strict;
use warnings 'all';

my @header = ( 'Unit#', 'Test_Name', 'Pin_Name', 'Measure_Data;' );
my $format = "%-10s %-15s %-15s %-s\n";

printf $format, @header;

my $unit;

while ( <> ) {

    if ( /^Device#:\s*(\d+)/ ) {
        $unit = $1;
        next;
    }

    chomp;

    my @fields = split /\s{2,}/;

    if ( $fields[3] eq 'PPST' and $fields[4] eq 'VDDIFF' ) {
        printf $format, $unit, $fields[3], $fields[4], $fields[7];
    }
}

输出

Unit#      Test_Name       Pin_Name        Measure_Data;
12         PPST            VDDIFF          3.8867 uA
50         PPST            VDDIFF          3.6867 uA
51         PPST            VDDIFF          3.5867 uA

答案 1 :(得分:-1)

好的,首先关闭:

  • use strict;use warnings 'all';放在代码顶部。它们会阻止许多错误,这些错误会在以后绊倒你
  • 使用词法文件句柄打开3个参数是好的。 open ( my $input, '<', $infile )
  • 你应该经常检查open的返回代码,因为你以后会为自己节省一些痛苦。

从这一点来看,你的问题比你想象的要简单 - 你有Device#:表示的记录,所以我们可以设置一个记录分隔符。 $/

然后我们可以将您的数据块分解为行。我建议而不是使用数组指示,你最好在hash中使用命名字段:

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

open( my $output, '>', $outfile ) or die $!;
open( my $input,  '<', $infile1 ) or die $!;

my $pin_name  = 'VDDIFF';
my $test_name = 'PPST';

local $/ = 'Device#:';

#print header row - tab separated
print {$output} join( "\t", "Unit#", "Test_Name", "Pin_Name", "Measure_Data" ),"\n";


while (<$input>) {
    s/\b \b/_/g;    #turn "Test Name" into "Test_Name"
    #split this current chunk on linefeeds
    my @rows = split(/\n/);          

    #pop the first line, and extract the number from it
    my ($device_id) = shift(@rows) =~ m/(\d+)/;    
    next unless $device_id;
    my @header = split( ' ', shift(@rows) );    #read a header row
    for (@rows) {
        my %this_row;
        @this_row{@header} = split;
        if (    defined $this_row{'Test_Name'}
                    and $this_row{'Test_Name'} eq $test_name
                    and $this_row{'Pin'}       eq $pin_name )
        {
            print {$output} join( "\t",
                $device_id,       
                $this_row{'Test_Name'},
                $this_row{'Pin'}, 
                $this_row{'Measured'} ),
                    "\n";
        }
    }
}

close($input);
close($output);