2011-01-20 51 views
1

Perl專家 - 我試圖解決我的問題的過程變成了很多代碼,這在PERL中看起來像是我正確地接近了這一點。這是我的問題:Perl文本解析 - 固定的定界結構正在改變

我有一段文字(下面的例子),可以有不同數量的列數據之間的空白。我正在使用一個簡單的拆分,但現在的問題是,列「代碼」現在包含數據中的空間(我只佔最後一列中的空間)。什麼似乎是常數(儘管我無法訪問或控制源結構)是列之間至少有3個空格(可能更多,但不會更少)。

所以,我想說我的列分隔符令牌是「3個空格」,然後修剪每個數據中的數據以獲得我的實際列數據。

COL0 COL1 COL2 COL3   COL4 COL5 
    -  4 0.2  1  416489 463455 554 
      1 0.9  1   E1 
    0  3 1.4  14 E97-TEST 1 
    -  1 97.5 396   PASS Good 

我只是想把值變成6個變量。

注意:COL0可能沒有值。 COL4可能包含數據空間。 COL5可能不包含任何值,或包含空格的數據。所有固定的格式都是用空格(沒有選項卡或其他特殊字符)完成的。澄清 - 列不一致大小。一個文件可能具有13個字符的COL4,另一個文件具有21個字符的COL4。或者不像另一個SO成員那樣嚴格。

+0

可以一列從一個不同的每行之間的偏移開始?例如。 row1是`| 1 2 3 |`(3個空格),row2是`| 11111 2 3 |`(也是3個空格,但現在第二列的偏移量4比第一行大,因爲第二行的第一個值很寬) – DVK 2011-01-20 20:58:44

+0

不,列大小對於每個數據行是一致的文件。可以區分文件,但在文件中保持一致。 – Walinmichi 2011-01-20 21:03:02

+0

列標題是否真的存在? – Svante 2011-01-20 21:04:35

回答

2

如果你正在處理這樣嚴格的柱狀數據,unpack可能是你想要什麼:

#!perl 

use strict; 
use warnings; 
use 5.010; 

use Data::Dumper; 

my $data = <<EOD; 
COL0 COL1 COL2 COL3   COL4 COL5 
    -  4 0.2  1  416489 463455 554 
      1 0.9  1   E1 
    0  3 1.4  14 E97-TEST 1 
    -  1 97.5 396   PASS Good 
EOD 

my @lines = split '\n', $data; 
for my $line (@lines) { 
    my @values = unpack("a5 A7 A7 A7 A13 A*", $line); 
    print Dumper \@values; 
} 

這似乎你的價值觀轉儲到@values陣列如你所願,但他們將有領先的空間,你必須削減。

0

我知道CanSpice已經回答了(可能是更好的解決方案),但是您可以使用「$ /」設置輸入分隔符。這必須在局部範圍內完成(可能是一個子範圍),因爲它是一個全局變量,或者您可能會看到副作用。例如:

local $/ = " "; 
$input = <DATAIN>; # assuming DATAIN is the file-handler 

您可以使用一個很好的小正則表達式來裁剪空白。一個例子見Wikipedia

1

我會使用兩遍:在第一個,找到那些在每行中有空格的字符列;然後,與這些指數拆分或解包。之後進行空白修整。

你舉的例子:

COL0 COL1 COL2 COL3   COL4 COL5 
    -  4 0.2  1  416489 463455 554 
      1 0.9  1   E1 
    0  3 1.4  14 E97-TEST 1 
    -  1 97.5 396   PASS Good 

000011100001110000111000011100000000001110000000000 

1 S IN的最後一行顯示的列都是空格。

3

你需要弄清楚列的位置。作爲一個真的挺噁心的黑客,你可以讀取整個文件,然後串或線一起:那麼

my @file = <file>; 
chomp @file; 

my $t = ""; 
$t |= $_ foreach(@file); 

$ T將包含在只那裏總是在列空格字符列空格字符;其他列將包含二進制垃圾。現在有了一個零寬度匹配拆分它的非空間相匹配:

my @cols = split /(?=[^ ]+)/, $t; 

實際上,我們希望寬度列生成解壓縮()格式:

@cols = map length, @cols; 
my $format = join '', map "A$_", @cols; 

現在進程文件! :

​​3210

(此代碼只被輕輕測試。)