2011-02-13 28 views
1

我有以下數據(來自文本文件),我想分割/獲取每個元素,甚至是那些空白的元素(某些級別,因爲您可以看到未列出,意味着它們是0,所以我希望讓他們也)使用Perl和非結構化數據令牌化

CRN SUB  CRSE SECT COURSE TITLE   INSTRUCTOR  A A- B+ B  B- C+ C  C- D+ D  D- F I CR NC W  WN INV TOTAL 
----- --  ---- ---- ----------------- ----------------- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ----- 
33450 XX  9950 AIP OVERSEAS-AIP SPAI NOT FOUND                1 1    2 
33092 XX  9950 ALB ddddddd, SPN. vi NOT FOUND                1     1 
33494 XX  9950 W16 OVERSEAS Univ.Wes NOT FOUND                1     1 

          INSTRUCTOR TOTALS NOT FOUND    2            1 18 1 2   24 
          PERCENTAGE DISTRI NOT FOUND    8            4 75 4 8  ****** 

33271 PE 3600 001   Global Geography sfnfbg,dsdassaas  2 2 1 1 2 3 6 5 3 3 1      29 

          INSTRUCTOR TOTALS snakdi,plid   2 2 1 1 2 3 6 5 3 3 1      29 
          PERCENTAGE DISTRI krapsta,lalalal   7 7 3 3 7 10 21 17 10 10 3      *** 

,你可以看到,我沒有特定的分隔符,因爲一些成績缺失,如果他們沒有,我可以在問題已經從線上開始獲得所有的數據直到第一年級('A'),然後是所有的成績,並將它們分成/ \ s + /,但事實並非如此。 任何建議(如果有任何....)將是真棒。

感謝,

+6

這些列是否真的很不一致,或者這是一個糟糕的複製粘貼作業? – cjm 2011-02-13 10:27:09

回答

3

在某些列的地方有不規則的地方(請注意,第一個總值18和75部分在下一列),但如果你不需要他們,你可以嘗試這樣的事:

my @data; 

# skip header 
my $hdr = <DATA>; 
my $sep = <DATA>; 

while(<DATA>) { 
    chomp; 

    # skip empty and total lines 
    next if /^\s*$/ || /^[ ]{5}/; 

    push @data, [ 
     map { s/^\s+//; s/\s+$//; $_ }  # trim each column 
     unpack 'A6A7A7A7 A18A20 A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 A10', $_ 
    ]; 
} 

use Data::Dump; 
dd \@data; 

__DATA__ 
CRN SUB  CRSE ... 
----- --  ---- ... 

你可能需要調整列邊界在真實數據解壓模板,但這應該讓你開始。

3

這看起來像這將是最好寫或找一個基於列的文本解析器?我在CPAN上找到了DataExtract-FixedWidth,但沒有親身體驗過它。格式看起來相當混亂,特別是列邊界上的數字。無論如何,你將不得不做一些預處理或啓發式......