2013-03-20 20 views
0

我在CSV文件中有數據(IP地址),它將成爲9-13列。如果其他列中沒有值,那麼在默認情況下,它應該只打印第9列中的內容。有一個輸出文件將打印一組值和第9列的值(如果值爲13存在)與一個靜態值連接以創建一個別名值。我的問題是,你如何有效地做到這一點?我有這樣的代碼工作:如何編寫Perl腳本來檢查x列以在每行返回值的另一行中輸出值

my $alias0= "ComponentAliases=['ComputerSystem:$columns[9]'];\n"; 
my $alias1= "ComponentAliases=['ComputerSystem:$columns[9]','ComputerSystem:$columns[10]'];\n"; 
my $alias2= "ComponentAliases=['ComputerSystem:$columns[9]','ComputerSystem:$columns[10]','ComputerSystem:$columns[11]'];\n"; 


     print BAROC "ComputerSystem;\n"; 
     if(($columns[11] != '')&&($columns[10] != '')) { print BAROC $alias2 } 
     elsif(($columns[11] == '')&&($columns[10] != '')) { print BAROC $alias1 } 
     elsif(($columns[11] == '')&&($columns[10] == '')) { print BAROC $alias0 } 

這個工程做我想做的事情,但有一個機會,CSV文件將在列9-13或9-11值,等我輕鬆認爲靜態寫這篇文章會很好,但我希望有效地做到這一點,並理解並始終應用最佳實踐。我不熟悉Perl腳本,但不斷吸取它來解決工作中的問題。建議?

這是輸出,順便說一句:

ComponentAliases=['ComputerSystem:10.1.0.225','ComputerSystem:10.200.252.77','ComputerSystem:10.100.252.77']; 

回答

0

一個襯墊(不那麼優雅,但不知何故,我喜歡它):

print "ComponentAliases=[".join(",",map {"'ComputerSystem:$_'"} grep {$_ ne ""} @columns[9-13])."]\n"; 

或者如果你喜歡相同的代碼更易懂方法:

print( 
     "ComponentAliases=[", 
     join(
      ",", 
      map( 
       "'ComputerSystem:$_'", 
       grep (
         $_ ne "", 
         @columns[9-13] 
        ) 
       ) 
      ), 
     "]\n" 
    ); 
1
#!/usr/bin/env perl 

use strict; 
use warnings; 

use Text::CSV_XS; 

my $csv_in = Text::CSV_XS->new 
    or die Text::CSV_XS->error_diag; 

my $csv_out = Text::CSV_XS->new({ 
    always_quote => 1, 
    quote_char => q{'}, 
}) or die Text::CSV_XS->error_diag; 

while (my $row = $csv_in->getline(\*DATA)) { 
    my @aliases = map "ComputerSystem:$_", 
        grep defined && length, @$row[9 .. 13]; 
    if ($csv_out->combine(@aliases)) { 
     printf "ComponentAliases=[%s];\n", $csv_out->string; 
    } 
} 

__DATA__ 
0,1,2,3,4,5,6,7,8,10.1.0.225,10.200.252.77,,,,,,, 
0,1,2,3,4,5,6,7,8,10.1.0.225,10.200.252.77,10.100.252.77,,,,, 

出放:

C:\temp> gn 
ComponentAliases=['ComputerSystem:10.1.0.225','ComputerSystem:10.200.252.77']; 
ComponentAliases=['ComputerSystem:10.1.0.225','ComputerSystem:10.200.252.77','Co 
mputerSystem:10.100.252.77'];
1

高效現在意味着維護。試圖保存一個或兩個命令不會爲您節省很多時間。事實上,如果編譯器無法弄清楚你正在做什麼,它可能會使程序更加低效。

重要的是可讀性。擺脫$alias的東西。它只是讓你很難看到你的代碼正在做什麼,並且最終會產生各種各樣的副作用。

缺少空白還會讓你的代碼更加難以理解。一旦我重新格式化了你的代碼,我立即發現了一個錯誤。你這樣做:

if (($columns[11] != '') && ($columns[10] != '')) 

然而,這是一個字符串比較。你需要這樣做:

if (($columns[11] ne '') && ($columns[10] ne '')) { 

或者,你甚至可以進一步簡化它:

if (not $column[10] and not $column[11]) { 

這使得你在尋找它很清楚是什麼,以及將工作列是否包含數字零,空字符串或未定義。

此代碼段正在使用您的邏輯,但我利用了print不會自動在字符串末尾添加\n這一事實。我簡單地繼續建設:

if ($columns[9]) { 
    print BAROC "ComputerSystem;\n"; 
    print BAROC "ComponentAliases=['ComputerSystem:$columns[9]'"; 

    if ($columns[10]) { 
     print BAROC ",ComputerSystem:$columns[10]"; 
    } 
    if ($columns[11]) { 
     print BAROC ",ComputerSystem:$columns[11]"; 
    } 
    print BAROC "];\n"; 
} 

您提到如果這些列中包含數據,您可能需要列9到13。爲什麼不使用循環?

if ($#columns >= 9) { #There are at least nine columns 
    print BAROC "ComputerSystem;\n"; 
    print BAROC "ComponentAliases=[ComputerSystem:$columns[9]"; 

    for my $column ((10..$#columns)) { 
     last if not $column[$column]; 
     print BAROC ",ComputerSystem:$columns[$columns]; 
    } 
    print BAROC "];\n"; 
} 

如果給了更多的時間,我敢肯定我可以清理更多的邏輯。但是,無論有9,10,11或43列的數據,這都會起作用。

相關問題