2012-01-13 71 views
3

我具有在單獨的線的形式,其中每行具有CSV狀格式文本:提取可選字段值

SOME BUNCH OF TEXT, FIELD_A: 12, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656 

字段的順序始終是相同的,但某些字段可能不存在。可以有感興趣的領域之間的其他領域,例如比較線之上,我可以得到下面還有:

SOME BUNCH OF TEXT, FIELD_A: 12, NOT_INTERESTED: 235, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656, FIELDS 

作爲處理這段文字我想和指定我的領域清潔CSV文件的結果接二連三:

12,0.2321,12:10:08 2011/07/22,656 

如果某些字段不存在那麼我想簡單的省略值(例如FIELD_B缺席):

12,,12:10:08 2011/07/22,656 

我該怎麼做使用像sed,perl或awk這樣的命令? 我試圖提取單場perl -pe 's/^.*?(FIELD_A: (.*?),)?.*?$/\2/'和失敗 - 正則簡單地忽略我的域,即使它提出

回答

2

可以使用awk與關聯數組,如下圖所示。循環遍歷字段並將其拆分爲:。然後將鍵值對存儲到關聯數組中。最後打印出你想要的字段。

awk -F, '{ 
split("",arr) 
for(i=1; i<=NF; i++){ 
    a=index($i, ":") 
    if(a != 0){ 
    # split on first colon to get key-value pair 
    key=substr($i,1,a-1) 
    val=substr($i,a+1) 

    # remove leading spaces from key and value 
    gsub(/^ */,"",key) 
    gsub(/^ */,"",val) 

    # store in an associative array 
    arr[key]=val 
    } 
} 
# print out the desired fields 
print arr["FIELD_A"]","arr["FIELD_B"]","arr["FIELD_C"]","arr["FIELD_D"] 
}' data.txt 
+0

您的解決方案的偉大工程。事實上,我期待一些正則表達式作爲解決方案,但似乎正則表達式無法解決我的問題。所以我們需要使用腳本。 – 2012-01-13 11:21:06

1

如何這樣(假設的Fileds名已知):

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

my @f = qw(FIELD_A FIELD_B FIELD_C FIELD_D); 
while(my $line = <DATA>) { 
    chomp $line; 
    my @r; 
    for(@f) { 
     if ($line =~ /$_:\s*([^,]+)/) { 
      push @r, $1; 
     } else { 
      push @r,''; 
     } 
    } 
    print join(',',@r), "\n"; 
} 
__DATA__ 
SOME BUNCH OF TEXT, FIELD_A: 12, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656 
SOME BUNCH OF TEXT, FIELD_A: 12, NOT_INTERESTED: 235, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656, FIELDS 
SOME BUNCH OF TEXT, FIELD_A: 12, NOT_INTERESTED: 235, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656, FIELDS 

輸出:

12,0.2321,12:10:08 2011/07/22,656 
12,0.2321,12:10:08 2011/07/22,656 
12,,12:10:08 2011/07/22,656 
+0

謝謝,我試過了,但得到錯誤'無法找到Modern/Perl.pm in @INC(@INC包含:/ etc/perl /usr/local/lib/perl/5.10.0/usr/local/share /perl/5.10.0/usr/lib/perl5/usr/share/perl5/usr/lib/perl/5.10/usr/share/perl/5.10/usr/local/lib/site_perl。)在for_perl第2行。 BEGIN失敗 - 編譯在for_perl第2行中斷了.'似乎我的perl版本不是現代的:)我相信它可以爲其他版本的perl工作。 – 2012-01-13 11:34:43

+0

@pavel_kazlou:只需刪除'使用Modern :: Perl'的行;'用'print'改變'say'。看我的編輯。 – Toto 2012-01-13 12:00:27

+0

現在這適用於我,謝謝。我已經投票答覆你的答案 – 2012-01-13 13:45:53