2012-02-02 156 views
1

我是新來的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

回答

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 
} 
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); 
} 
+0

它有編譯錯誤。 1.「warn」指令中有一個小括號。 2.-將'foundstart'變量聲明爲帶'$'的標量,並且在下一個正則表達式中,我認爲有'#'而不是'*'的拼寫錯誤。然後它會在我的測試中打印數字但百分比。 – Birei 2012-02-02 13:56:17

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; 
0

您可以通過在命令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

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