2012-07-24 68 views
1

我在尋找關於如何優化這個perl腳本的建議。Perl優化建議

我有這個腳本來做一些文件的重新格式化。該腳本執行以下操作:

  1. 讀取「|」從STDIN
  2. 分隔的文件刪除尾隨空白,
  3. 刪除 「NULL」 文本字符串從 「YYYY-MM-DD HH:MM」
  4. 的日期轉換列 「YYYYMMDD」 格式的日期格式。
  5. 打印到STDOUT,並做一個kluge以防止最後一列數據在NULL時丟失。每列的列數需要相同。

樣品輸入:

.091590.S   |CHF|SWX|2011-05-23 00:00|     77.25|     NULL|     NULL|  78.620000000000005|    NULL 
.091590.S   |CHF|SWX|2011-05-24 00:00|  77.599999999999994|     NULL|     NULL|     77.25|    NULL 
.091590.S   |CHF|SWX|2011-05-25 00:00|  77.760000000000005|     NULL|     NULL|  77.599999999999994|    NULL 
.091590.S   |CHF|SWX|2011-05-26 00:00|  77.430000000000007|     NULL|     NULL|  77.760000000000005|    NULL 
.091590.S   |CHF|SWX|2011-05-27 00:00|  77.909999999999997|     NULL|     NULL|  77.430000000000007|    NULL 
.091590.S   |CHF|SWX|2011-05-30 00:00|  78.060000000000002|     NULL|     NULL|  77.909999999999997|    3506 

FormattingScript.pl [COL]

在哪裏[COL]可以是單一數目或由逗號分隔的號碼列表。 該輸入確定哪個或哪些列需要日期轉換。

@updcol = split(',',@ARGV[0]); 

while (<STDIN>) 
{ 
     s/.$/|DATAEND/g; ## USING THIS TO KEEP FROM TRUNCATING NULL LAST COLUMN 
     s/^\s*//g; 
     s/\s*$//g; 
     s/\s*\|/\|/g; 
     s/\|\s*/\|/g; 
     s/\|NULL\|/\|\|/g; 
     s/\|NULL\s*$/\|/g; 
     s/\|NULL\s*/\|/g; 
     s/\|NULL$/\|/g; 
     @dataline = split('\|',$_); 
if (@updcol[0] != 999) { ## REFORMAT DATES IF PARAM IS NOT 999 
     foreach my $col (@updcol) { 
     $dataline[$col]=substr($dataline[$col],0,4).substr($dataline[$col],5,2).substr($dataline[$col],8,2); 
     }} 
     $dataline[-1]=""; 
     $line=join('|',@dataline); 
     print substr($line,0,-1)."\n"; 
} 

exit 0; 

樣本輸出:

.091590.S|CHF|SWX|2011-05-23 00:00|77.25|||78.620000000000005| 
.091590.S|CHF|SWX|2011-05-24 00:00|77.599999999999994|||77.25| 
.091590.S|CHF|SWX|2011-05-25 00:00|77.760000000000005|||77.599999999999994| 
.091590.S|CHF|SWX|2011-05-26 00:00|77.430000000000007|||77.760000000000005| 
.091590.S|CHF|SWX|2011-05-27 00:00|77.909999999999997|||77.430000000000007| 
.091590.S|CHF|SWX|2011-05-30 00:00|78.060000000000002|||77.909999999999997|3506 
+2

請記住[優化俱樂部的規則](http://stackoverflow.com/a/177132/554546)。爲什麼你需要優化這個程序? – 2012-07-24 21:23:35

回答

9

任何的優化將是微,這意味着你將需要拿出基準並開始測試做同樣的事情不同的方式。

清理代碼比從優化代碼中獲益更多。

my @date_cols = split(/,/, shift(@ARGV)); 

while (<>) { 
    #chomp; # Redundant. 
    my @fields = split(/\|/, $_, -1); 

    for (@fields) { 
     s/^\s+//; 
     s/\s+\z//; 
     s/^NULL\z//; 
    } 

    for (@fields[@date_cols]) { 
     s/^(....)-(..)-(..).*/$1$2$3/s; 
    } 

    print(join('|', @fields), "\n"); 
} 
+2

請注意['split']的第三個參數(http://perldoc.perl.org/functions/split.html)。 – ikegami 2012-07-24 21:47:25

+0

修復了一個小錯誤。刪除了多餘的「chomp」。 – ikegami 2012-07-24 21:50:49

+0

謝謝@ikegami。這是一個非常有用的練習。它讓我想起我仍然需要學習多少。我必須添加而不是<>,以便腳本能夠識別我傳遞的參數和流。 – DataTsar 2012-07-25 13:10:16

2

您或許可以使用Regexp::Assemble來優化您的regexes。這將使您能夠將所有正則表達式組合成一個正則表達式,這可能會比運行多個正則表達式更快地執行。