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

时间:2012-02-02 11:23:35

标签: perl file

我是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;

需要更改的是“my @columns = split ...”行。目前,只要它有'9个空格',它就会分割$ line标量。由于元素数的位数可以变化,这是提取数据的不良方式。是否可以只从左到右阅读,省略所有空格并记录数字,直到数字后跟更多空格(这样会忽略百分比值)?

5 个答案:

答案 0 :(得分:1)

#!/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
}

答案 1 :(得分:1)

使用触发器的单线:

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

答案 2 :(得分:0)

#!/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);
}

答案 3 :(得分:0)

#!/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;

答案 4 :(得分:0)

你可以通过在命令shell中运行这个单行来完成它。

On * 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