从TXT提取特定列数据存到Excel中
本帖最后由 情节可以很简单 于 2018-01-16 17:24 编辑哪位大神能提供下 下面两种模块的安装包啊,或给个指引,没用过这个模块。
我用Windows系统处理数据,可是开头就给我难住了,这些指令无法执行。
我搜了好多网址啥的都不行啊!
use Win32::OLE
use Spreadsheet::WriteExcel
另外我在activeperl安装路径中发现了OLE.pm及一些文件夹,那怎么不能用呢。
activeperl 有自己的模块管理。好象说 activepm什么的。 本帖最后由 情节可以很简单 于 2018-01-16 17:19 编辑
处理学习实践阶段,求指导!谢谢!!!
我把要处理的文本放这吧,不用输入到Excel了。
输入文本A为:下面是输入文本的一部分(省略号下面还有一些无用的英文说明),
其他部分的格式也是这样,但行数量有异。
=========================================================
Device#: 19-24
die position: (-7,1) site 2
die position: (-6,1) site 3
die position: (-5,1) site 4
die position: (-4,1) site 5
die position: (-3,1) site 6
die position: (-2,1) site 7
NumberSite Result Test Name Channel Low Measured High
0 4 PASS Con 56 -1.0000 V -395.4362 mV -100.0000 mV
0 5 PASS ib_trim1 58 -1.0000 V -555.5970 mV -100.0000 mV
1 4 FAIL Con 40 -1.0000 V -405.8470 mV -100.0000 mV
1 2 PASS ib_trim0 42 -1.0000 V -556.9597 mV -100.0000 mV
2 4 FAIL ib_trim0 57 -1.0000 V -398.5833 mV -100.0000 mV
2 5 PASS Con 59 -1.0000 V -553.6025 mV -100.0000 mV
.................................................................
输出文本B为:“PASS”的 ib_trim 对应的site坐标及 Measured 值。
Device#: 19-24
(-4,1) ib_trim1 -555.5970 mV
(-7,1) ib_trim0 -556.9597 mV
#-----------------------------------------以下我的程序只实现了相关列提取:但是坐标不会匹配。
Device#: 19-24
5 ib_trim1 -555.5970 mV
2 ib_trim0 -556.9597 mV
回复 3# 情节可以很简单
粗略地写一个
use Modern::Perl;
STDOUT->autoflush(1);
my $file = "src.txt";
open my $fh, "<", $file or die "$!";
my $line;
my %site;
while ( $line = <$fh> )
{
if ( $line=~/^die position: (.*)\s+site (\d+)/i )
{
$site{ $2 } = $1;
}
if ( $line=~/\d+\s+(\d+)\s+PASS\s+(ib_trim\d+).*?(-?\d+\.\d+ mV)/i )
{
printf "%s\t%s\t%s\n", $site{$1}, $2, $3;
}
}
close $fh;
或者先把数据存到哈希表中,可以按标题查询
use Modern::Perl;
STDOUT->autoflush(1);
my $file = "src.txt";
open my $fh, "<", $file or die "$!";
my $line;
my %site;
my @title;
my @table;
my $ti;
while ( $line = <$fh> )
{
if ( $line=~/^die position: (.*)\s+site (\d+)/i )
{
$site{ $2 } = $1;
}
elsif ( $line=~/^Number/ )
{
@title = split /\s{2,}/, $line;
}
elsif ( $line=~/^\d+\s+/ )
{
$ti = 0;
push @table, { map { $title[$ti++] => $_ } split /\s{2,}/, $line };
}
}
close $fh;
for my $d ( @table )
{
if ( $d->{'Result'} =~/PASS/i and $d->{'Test Name'}=~/ib_trim/i )
{
printf "%s\t%s\t%s\n", $site{$d->{'Site'}}, $d->{'Test Name'}, $d->{'Measured'};
}
}
本帖最后由 情节可以很简单 于 2018-01-17 16:45 编辑
回复 5# 523066680
谢谢回复!我有点不知道该怎么描述:
1.首先我用的是Windows系统,modern::perl 我从CPAN下载了包在perl路径下解压了。
但运行程序时依然提示错误(就把他#注释掉了),所以我开头变为:
#!C:\perl64\bin
use strict;
use warnings;
use 5.016;
use autodie;
这样您提供的两个脚本输出结果是正确的!(我用三楼贴出来的部分文本示例)...
2.当我用 我的源文件为输入时,提示错误(这是我之前表述简略造成的,抱歉):
第一个脚本这句“if ( $line=~/\d+\s+(\d+)\s+PASS\s+(ib_trim\d+).*?(-?\d+\.\d+ mV)/i )”中我的源数据后面单位“mV”不是固定的
第二个脚本“if ( $d->{'Result'} =~/PASS/i and $d->{'Test Name'}=~/ib_trim/i )”
错误提示“Use of unintialized value in pattern match <m/ /> at a.pl line 41”
这个原因我在想可能是因为我的源文件 标题和下面对应数据 不是对齐的,这个该怎么办,我之前提取的时候是按列(电流单位也占一列):“print C (split),"\t",(split),"\t",(split)," ",(split),"\n";”
下面是源文件局部:是两个部分数据的交界处(每一部分都是以“Device#:x~y ” 开始,且每一部分的坐标“die position:”也是不同的)。
... . .... ....... ......... ............ ............ ............
8 1 FAIL ib_trim3 test-1 -1.2800 uA -2.1310 uA -960.0000 nA
8 2 FAIL ib_trim3 test-1 -1.2800 uA -544.6071 pA -960.0000 nA
8 3 FAIL ib_trim3 test-1 -1.2800 uA 762.9061 pA -960.0000 nA
8 4 FAIL ib_trim3 test-1 -1.2800 uA -23.0533 nA -960.0000 nA
Site Failed tests/Executed tests
------------------------------------
0 5 9
1 5 9
2 5 9
3 5 9
4 5 9
Site Sort Bin
------------------------------------
0 40 4
1 40 4
2 40 4
3 40 4
4 40 4
=========================================================================
Device#: 6-10
die position: (7,1) site 0
die position: (8,1) site 1
die position: (9,1) site 2
die position: (10,1) site 3
die position: (11,1) site 4
NumberSite Result Test Name Pin Channel Low Measured High
0 0 PASS Con test75 -1.0000 V -546.8680 mV -100.0000 mV
0 1 PASS Con test74 -1.0000 V -559.3652 mV -100.0000 mV
0 2 PASS Con test73 -1.0000 V -556.2122 mV -100.0000 mV
0 3 PASS Con test72 -1.0000 V -560.9373 mV -100.0000 mV
0 4 PASS Con test15 -1.0000 V -545.2946 mV -100.0000 mV
1 0 FAIL ib_trim1 test-1 -1.2800 uA -1.1330 nA -960.0000 nA
1 1 FAIL ib_trim1 test-1 -1.2800 uA -2.5713 nA -960.0000 nA
1 2 FAIL ib_trim1 test-1 -1.2800 uA -915.8693 nA -960.0000 nA
1 3 PASS ib_trim1 test-1 -1.2800 uA -1.1828 uA -960.0000 nA
1 4 FAIL ib_trim1 test-1 -1.2800 uA 3.0930 nA -960.0000 nA
2 0 PASS ib_trim0 test-1 -1.2800 uA -1.0120 uA -960.0000 nA
... .. ...... ......... ......... ............ .............. ................
本帖最后由 523066680 于 2018-01-18 12:38 编辑
回复 6# 情节可以很简单
哦,后面的多了一个Pin列。能不能发一个更完整的源文件(压缩)上来,或者上传网盘。
第二个代码找出问题了
Number,Site Result,Test Name,Pin,Channel Low,Measured,High
Site Result 是两个列的抬头,Test Name 是单个列的抬头,中间都是一个空格。
前三列的数据内容是等宽的,1楼给出的示例是这样的 (Site 和 Result 之间有多个空格,可以作为区分):
NumberSite Result
0 4 PASS
0 5 PASS
1 4 FAIL
后面补充的示例是这样的(Site 和 Result 之间只有1个空格)?
NumberSite Result
0 0 PASS
0 1 PASS
0 2 PASS
https://gist.coding.net/u/ViANG/b6a859d73042403494be6fd74836e6a3 本帖最后由 523066680 于 2018-01-18 12:33 编辑
use strict;
use warnings;
STDOUT->autoflush(1);
my $file = "src_more.txt";
open my $fh, "<", $file or die "$!";
my $line;
my %site;
my @title;
my @table;
my $ti;
while ( $line = <$fh> )
{
if ( $line=~/Device#.*/ )
{
dump_table(\@table) if @table;
print $&, "\n";
@title = ();
@table = ();
%site= ();
}
elsif ( $line=~/^die position: (.*)\s+site (\d+)/i )
{
$site{ $2 } = $1;
}
elsif ( $line=~/^Number/ )
{
@title = map { $_ !~/Test Name/i ? split " ", $_ : $_ } split /\s{2,}/, $line;
# 只有 Test Name 是包含空格的 title
}
elsif ( $line=~/^\d+\s+/ )
{
$ti = 0;
push @table, { map { $title[$ti++] => $_ } split /\s{2,}/, $line };
}
}
close $fh;
dump_table(\@table) if @table;
sub dump_table
{
my $table = shift;
for my $d ( @$table )
{
if ($d->{'Result'} =~/PASS/i
and
$d->{'Test Name'}=~/ib_trim/i )
{
printf "%s\t%s\t%s\n",
$site{ $d->{'Site'} },
$d->{'Test Name'},
$d->{'Measured'}
;
}
}
}
Device#: 19-24
(-4,1) ib_trim1 -555.5970 mV
(-7,1) ib_trim0 -556.9597 mV
Device#: 6-10
(10,1) ib_trim1 -1.1828 uA
(7,1) ib_trim0 -1.0120 uA ActivePerl用PPM安装模块,在运行框输入PPM回车即可。
给一段excel文件生成代码,供你参考:
#!/usr/bin/perl
use strict;
use warnings;
use Spreadsheet::WriteExcel;
my $file = "Excel_Example.xls";
my $workbook = Spreadsheet::WriteExcel->new($file);
$workbook->set_properties(
title => 'Excel_Example',
author => 'Limeng',
company=> 'BlueIdea Software Lab.',
);
my $worksheet = $workbook->add_worksheet('Limeng');
# Create a format for the column headings
my $header = $workbook->add_format(
font => 'Arial',
bold => 1,
size => 12,
color => 'blue',
align => 'center',
valign => 'vcenter',
);
my $red = $workbook->add_format(
size => 11,
align => 'right',
valign => 'vcenter',
bg_color => 'red',
num_format => 0x04,
);
my $pink = $workbook->add_format(
size => 11,
align => 'right',
valign => 'vcenter',
bg_color => 33,
num_format => 0x04,
);
# Set the column width for columns 1, 2, 3 and 4
$worksheet->set_column(0, 3, 10);
# Write datas
$worksheet->write('A1','Test1',$header);
$worksheet->write('B1','Test2',$header);
$worksheet->write('C1','Test3',$header);
$worksheet->write('A2','2000',$red);
$worksheet->write('B2','-50000',$pink);
$worksheet->write('C2','=A2+B2',$red);
$workbook->close();
print "Excel file write OK!";
<>;
发重复了!
页:
[1]
2