提取从文本文件中的特定数据在Perl

问题描述:

我是新来的Perl,我试图从一个文件,它看起来像这样提取的具体数据:提取从文本文件中的特定数据在Perl

Print of 9 heaviest strained elements:  


    Element no Max strain 
     20004   9.6 % 
     20013   0.5 % 
     11189   0.1 % 
     20207   0.1 % 
     11157   0.1 % 
     11183   0.0 % 
     10665   0.0 % 
     20182   0.0 % 
     11160   0.0 % 


================================================== 

我想只提取单元号(20004 ,20013等)并将它们写入一个新文件。文件的读取应该在到达行(=========)时立即结束,因为文件中稍后会有更多元素编号和相同的标题。 希望是有道理的。 任何建议非常感谢!

我现在有这样的代码,这给了我的号码列表,最大10连胜:

my $StrainOut = "PFP_elem"."_$loadComb"."_"."$i"; 
open DATAOUT, ">$StrainOut" or die "can't open $StrainOut"; # Open the file for writing. 

open my $in, '<', "$POSTout" or die "Unable to open file: $!\n"; 
my $count = 0; 

while(my $line = <$in>) { 
    last if $line =~/={10}\s*/; 
    if ($line =~ /% *$/) { 
    my @columns = split "   ", $line; 
    $count++; 
    if($count % 10 == 0) { 
     print DATAOUT "$columns[1]\n"; 
    } 
    else { 
     print DATAOUT "$columns[1] "; 
    }  
    } 
} 
close (DATAOUT); 
close $in; 

什么需要改变的是“我的@columns =分裂...”行。目前,只要它有'9个空格',就会分割$ line标量。由于元素数字的位数可能会有所不同,这是一种糟糕的数据提取方式。是否可以从左至右进行读取,省略所有空格并仅记录数字,直到数字后面有更多空格(百分比值被忽略)?

+0

这似乎工作:我的@columns =拆分(/ \ S + /,$行); – 2012-02-02 16:18:35

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

while (<>) {      # read the file line by line 
    if (/% *$/) {     # if the line ends in a percent sign 
     my @columns = split;  # create columns 
     print $columns[0], "\n"; # print the first one 
    } 
    last if /={10}/;    # end of processing 
} 

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

while (my $f= shift) { 
    open(F, $f) or (warn("While opening $f: $!", next); 
    my foundstart=0; 
    while(<F>) { 
    ($foundstart++, next) if /^\s#Element/; 
    last if /\s*=+/; 
    print $_ if $foundstart; 
    } 
    $foundstart=0; 
    close(F); 
} 
+0

它有编译错误。 1.“warn”指令中有一个小括号。 2.-将'foundstart'变量声明为带'$'的标量,并且在下一个正则表达式中,我认为有'#'而不是'*'的拼写错误。然后它会在我的测试中打印数字但百分比。 – Birei 2012-02-02 13:56:17

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

open my $rh, '<', 'input.txt' or die "Unable to open file: $!\n"; 
open my $wh, '>', 'output.txt' or die "Unable to open file: $!\n"; 

while (my $line = <$rh>) {   
    last if $line =~ /^ ={50}/; 
    next unless $line =~ /^ {6}(\d+)/; 
    print $wh "$1\n"; 
} 

close $wh; 

您可以通过在命令shell中运行此一班轮做。

在* nix:

cat in_file.txt | perl -ne 'print "$1\n" if (m/\s*(\d+)\s*\d+\.\d+/)' > out_file.txt 

在Windows上:

type in_file.txt | perl -ne "print qq{$1\n} if (m/\s*(\d+)\s*\d+\.\d+/)" > out_file.txt 
+0

但是,如果达到等号的行,他想停止从文件中读取数据。 – flesk 2012-02-02 12:25:31

+1

这只猫是一个过程的浪费。 -n开关导致对@ARGV中的文件名进行迭代,就好像你写了LINE:while(){... – JRFerguson 2012-02-02 13:17:11

一个班轮使用触发器:

perl -ne ' 
    if (m/\A\s*(?i)element\s+no/ .. ($end = /\A\s*=+\s*\Z/)) { 
    printf qq[$1\n] if m/\A\s*(\d+)/; 
    exit 0 if $end 
    } 
' infile 

结果:

20004 
20013 
11189 
20207 
11157 
11183 
10665 
20182 
11160