2013-07-16 96 views
1

我正在慢慢學習更多的PERL,並且需要一些幫助來解決我正面臨的問題。我有一個以csv格式給出的excel電子表格的輸入文件。在電子表格中,如果行中的一個單元格值爲「LOV」,則它們將合併單元格並給出值列表。我需要抓住與該LOV一起出現的下一個X行,然後將該LOV與同一行中的其他值一起輸出到單行中。所以這裏是輸入文件的樣子:基於特定行中的值獲取多行輸入文件

Intro |Input|Middle |PPP|Requirement|Manual|Text||| 
Intro |Input|END |PPP|Design|Manual|LOV|"Ancestory 
Red 
Blue 
Purple 
Orange 
Yellow"|| 
Intro |Output|END |PPP|Design|Automatic|Number||| 

該文件看起來像這樣,並將重複類似於上面的數據。輸出將根據文本,LOV,編號ETC放在不同的文件中。我需要得到的LOV輸出如下所示:

Intro |END |LOV|"Ancestory Red Blue Purple Orange Yellow"|| 

我完全失去了如何解決這個問題。我可以使用數組來獲取引用內的下一行嗎?我可以抓住所有其他線路,但迄今爲止,這是我的邏輯看起來像。

my @LOV; 
while(<file1>){ 

      my($line) = $_; 
      chomp $line; 
      if $line == "LOV" 
      { 

       push @LOV, $_; 
       while (<file1>) 
       { 
        last if /^$/; 
        push @LOV, $_; 
       }      
        print file2 "$output\n"; 
      } 
      else 
      { 


       if ("NUMBER") 
       { 
        print file3"output"; 
       } 
       else if ("Text") 
       { 
        print file4"output"; 
       } 

      } 

我不知道我是否應該以不同的方式閱讀文件,但任何建議或幫助將是偉大的!謝謝你提供的任何東西。

回答

4

只是好奇。你用什麼書來學習Perl?

你的編碼風格是方式,過時的方式。您不是第一個學習Perl的人,並且使用的語法風格始於20世紀80年代後期,所以我只是好奇人們用來學習Perl的市場上的書(或網頁)。

有關Perl的奇妙之處之一是它有很多模塊可以處理你想要的大部分內容。在這種情況下,你需要使用Text::CSV模塊與他們的嵌入式NL讀到那篇文章的時候,會做所有繁重的你:

use warnings; 
use strict; 
use autodie; 
use feature qw(say); 

use Text::CSV; 

my $spreadsheet = Text::CSV->new (
    { 
     binary  => 1, 
     sep_char => "|", 
     eol   => $/, 
    } 
); 
open my $file, "<:crlf", "text.csv"; 

while (my $row = $spreadsheet->getline($file)) { 
    my @columns = @{ $row }; 
    for my $field (@columns) { 
     $field =~ s/\n/, /g; 
    } 
    say join " | ", @columns; 
} 

這會打印出:

Intro | Input | Middle | PPP | Requirement | Manual | Text | | | 
Intro | Input | END | PPP | Design | Manual | LOV | Ancestory, Red, Blue, Purple, Orange, Yellow | | 
Intro | Output | END | PPP | Design | Automatic | Number | | | 

不幸,它採用面向對象符號它可以是一個有點混亂,但我會努力的點點打破這種分離位:

首先,你可能需要安裝Text::CSV。你可以做到這一點與下面的命令:

$ cpan install Text::CSV 

這應該在Windows正常工作,如果你有安裝Strawberry Perl或的ActivePerl。

如果你在Linux或Mac上,你需要這樣做:

$ sudo cpan install Text::CSV 

而且,你需要你的密碼。

安裝完成後,如果您願意,也可以安裝Text::CSV_XS。這使得Text :: CSV更快,特別是如果你真的有非常大的電子表格。

讓我們走這條線,由線:

前四行與use開始是標準的編譯指示,應在所有程序。 strict將防範馬虎的錯誤,warnings將幫助您捕捉其他類型的錯誤,如使用不包含任何值的變量。

my $spreadsheet = Text::CSV->new正在創建一個對象。這是你將用來操作你的文件。這有三個參數。 binary允許多個內襯數據(如你所擁有的)。 sep_char表示您的分隔符不是逗號,而是|符號。 eol我不太確定非常重要 - 尤其是當我使用<:crlf打開文件時處理Unix/Windows問題,該文件會將crlf的實例轉換爲lf的實例。

我打開我的文件並使用getline方法讀取我的行。這將讀取你的多行,而不必計算行數或任何東西。

的:

my @columns = @{ $rows }; 

是有點麻煩。 Perl變量都基於單個值。當然你有散列和數組,但它們是單值列表。有時候,你需要將值作爲一組來處理,而Perl使用引用。 $rows是指向我的列的數組的指針。我是取消引用的參考並創建了一個名爲@columns的真實數組。閱讀Reference Tutorial瞭解更多信息。

$field =~ s/\n/, /g;只是用逗號代替新行的任何實例。

最後,我只是使用say命令和使用join將所有行連接到一個單獨的字符串中打印出來,並將它們分開打印出來。

注意我不需要計算和處理多行的行。 Text::CSV模塊爲我做。它很簡短,易於理解,並且即使多行字段位於電子表格中間也可以工作。

+0

我覺得我需要一口白蘭地酒,也許在讀完這個答案後小睡一會兒。優秀! –

+0

我一直在飛行中學習。沒有書,也沒有真正的老師只是在網上教程和通過其他人。我可以告訴現在我的原始代碼有多糟糕。謝謝你的回答,這遠遠超過我的預期。有沒有你可能推薦的書? – user1258104

+0

@ user1258104 - 一個開始的好地方:http://modernperl.net –