Chinaunix

标题: 从TXT提取特定列数据存到Excel中 [打印本页]

作者: 情节可以很简单    时间: 2018-01-15 16:56
标题: 从TXT提取特定列数据存到Excel中
本帖最后由 情节可以很简单 于 2018-01-16 17:24 编辑

哪位大神能提供下 下面两种模块的安装包啊,或给个指引,没用过这个模块。
我用Windows系统处理数据,可是开头就给我难住了,这些指令无法执行。
我搜了好多网址啥的都不行啊!
use Win32::OLE
use Spreadsheet::WriteExcel
另外我在activeperl安装路径中发现了OLE.pm及一些文件夹,那怎么不能用呢。

作者: q1208c    时间: 2018-01-15 18:45
activeperl 有自己的模块管理。好象说 activepm什么的。
作者: 情节可以很简单    时间: 2018-01-16 17:11
本帖最后由 情节可以很简单 于 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

Number  Site   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


作者: 523066680    时间: 2018-01-16 19:17
回复 3# 情节可以很简单

粗略地写一个
  1. use Modern::Perl;
  2. STDOUT->autoflush(1);

  3. my $file = "src.txt";
  4. open my $fh, "<", $file or die "$!";
  5. my $line;
  6. my %site;

  7. while ( $line = <$fh> )
  8. {
  9.     if ( $line=~/^die position: (.*)\s+site (\d+)/i )
  10.     {
  11.         $site{ $2 } = $1;
  12.     }

  13.     if ( $line=~/\d+\s+(\d+)\s+PASS\s+(ib_trim\d+).*?(-?\d+\.\d+ mV)/i )
  14.     {
  15.         printf "%s\t%s\t%s\n", $site{$1}, $2, $3;
  16.     }
  17. }
  18. close $fh;
复制代码


作者: 523066680    时间: 2018-01-16 19:44
或者先把数据存到哈希表中,可以按标题查询

  1. use Modern::Perl;
  2. STDOUT->autoflush(1);

  3. my $file = "src.txt";
  4. open my $fh, "<", $file or die "$!";
  5. my $line;
  6. my %site;
  7. my @title;
  8. my @table;
  9. my $ti;

  10. while ( $line = <$fh> )
  11. {
  12.     if ( $line=~/^die position: (.*)\s+site (\d+)/i )
  13.     {
  14.         $site{ $2 } = $1;
  15.     }
  16.     elsif ( $line=~/^Number/ )
  17.     {
  18.         @title = split /\s{2,}/, $line;
  19.     }
  20.     elsif ( $line=~/^\d+\s+/ )
  21.     {
  22.         $ti = 0;
  23.         push @table, { map { $title[$ti++] => $_ } split /\s{2,}/, $line };
  24.     }
  25. }
  26. close $fh;

  27. for my $d ( @table )
  28. {
  29.     if ( $d->{'Result'} =~/PASS/i and $d->{'Test Name'}=~/ib_trim/i )
  30.     {
  31.         printf "%s\t%s\t%s\n", $site{$d->{'Site'}}, $d->{'Test Name'}, $d->{'Measured'};
  32.     }
  33. }
复制代码


作者: 情节可以很简单    时间: 2018-01-17 15:41
本帖最后由 情节可以很简单 于 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)[1],"\t",(split)[3],"\t",(split)[8]," ",(split)[9],"\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

Number  Site Result   Test Name       Pin   Channel Low            Measured       High              
0       0    PASS     Con                       test  75      -1.0000 V      -546.8680 mV   -100.0000 mV         
0       1    PASS     Con                       test  74      -1.0000 V      -559.3652 mV   -100.0000 mV         
0       2    PASS     Con                       test  73      -1.0000 V      -556.2122 mV   -100.0000 mV         
0       3    PASS     Con                       test  72      -1.0000 V      -560.9373 mV   -100.0000 mV     
0       4    PASS     Con                       test  15      -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 10:03
本帖最后由 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 之间有多个空格,可以作为区分):
  1. Number  Site   Result  
  2. 0            4      PASS   
  3. 0            5      PASS  
  4. 1            4      FAIL   
复制代码
后面补充的示例是这样的(Site 和 Result 之间只有1个空格)?
  1. Number  Site Result  
  2. 0       0    PASS
  3. 0       1    PASS
  4. 0       2    PASS  
复制代码
https://gist.coding.net/u/ViANG/b6a859d73042403494be6fd74836e6a3
作者: 523066680    时间: 2018-01-18 11:13
本帖最后由 523066680 于 2018-01-18 12:33 编辑


[Finished in 0.4s]
作者: iamlimeng    时间: 2018-01-28 10:47
ActivePerl用PPM安装模块,在运行框输入PPM回车即可。

给一段excel文件生成代码,供你参考:
  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;
  4. use Spreadsheet::WriteExcel;

  5. my $file = "Excel_Example.xls";
  6. my $workbook = Spreadsheet::WriteExcel->new($file);
  7. $workbook->set_properties(
  8.         title    => 'Excel_Example',
  9.         author   => 'Limeng',
  10.          company  => 'BlueIdea Software Lab.',
  11. );
  12. my $worksheet = $workbook->add_worksheet('Limeng');

  13. # Create a format for the column headings
  14. my $header = $workbook->add_format(
  15.         font => 'Arial',
  16.         bold => 1,
  17.         size => 12,
  18.         color => 'blue',
  19.         align => 'center',
  20.         valign => 'vcenter',
  21. );
  22. my $red = $workbook->add_format(
  23.         size => 11,
  24.         align => 'right',
  25.         valign => 'vcenter',
  26.         bg_color => 'red',
  27.          num_format => 0x04,
  28. );
  29. my $pink = $workbook->add_format(
  30.         size => 11,
  31.         align => 'right',
  32.         valign => 'vcenter',
  33.         bg_color => 33,
  34.          num_format => 0x04,
  35. );

  36. # Set the column width for columns 1, 2, 3 and 4
  37. $worksheet->set_column(0, 3, 10);

  38. # Write datas
  39. $worksheet->write('A1','Test1',$header);
  40. $worksheet->write('B1','Test2',$header);
  41. $worksheet->write('C1','Test3',$header);
  42. $worksheet->write('A2','2000',$red);
  43. $worksheet->write('B2','-50000',$pink);
  44. $worksheet->write('C2','=A2+B2',$red);
  45. $workbook->close();

  46. print "Excel file write OK!";
  47. <>;
复制代码



作者: iamlimeng    时间: 2018-01-28 10:48
发重复了!
作者: 情节可以很简单    时间: 2018-02-01 14:42
回复 8# 523066680
您好,前段时间瞎忙活了一阵。抱歉没能及时回复。您给的程序目前我没有实现想要结果。
但是您分析的标题是对的,只有test name是两个单词的。
我想您的脚本肯定能实现,但我还需好好运行运行,改改加理解。
我在您之前给的答案中稍添加了一句,就实现了。
    if ( $line=~/\d+\s+(\d+)\s+PASS\s+(bgr_trim.*?/i )
    {      
        my @ss=split(/\s+/,$line);     ##将条件行分成列
        printf M "%s\t%s\t%s\t%s\n", $site{$1}, $2, $ss[9],$ss[10]; ###加了“ $ss[9],$ss[10]”我需要的值和单位所在列
    }

最后!给您拜个早年吧!新年快乐!祝您全家人幸福安康!发大财~~



作者: 情节可以很简单    时间: 2018-02-01 18:12
回复 9# iamlimeng

十分感谢!虽然我还没有装好 写Excel模块,但是能看懂您的提示。以便将来使用!祝您新年快乐!





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2