CGI-BBS > CGI > Perl > 20万行のファイルを高速に読み込み、数字だけを抽出したい。


カレッヂ
カレッヂ


質問者 dreamerYK  投稿日 2005/7/12(火) 14:21:28
初めて投稿させていただきます、perl & cgi 初心者です。

早速ですが、20万行程度(1列80文字)ある英数字の混在文(ファイルサイズは約7メガ)から、
ある法則に従った数字部分のみを抽出する処理を考えています。

---以下、読み込みたいファイル内容-----------------------------------------
〜略〜
#outgoing#
  ht-1stat    ht-1stok    ht-altat    ht-altok    ans-comp    cong        
  0000000000  0000000000  0000000000  0000000000  0000000000  0000000000
  dur-absy    dsz         ratpt       usg-bsy     usg-ans     usg-idle    
  0000000000  0000000000  0000000000  00000.00    00000.00    00058.00  
  usg-mnt     usg-inst    usg-flt     usg-cns     inst        ins         
  00000.00    00058.00    00000.00    00000.00    0000000058  0000000058
  flt         blk         
  0000000000  0000000000
〜略〜
#atm-qos1#
  cell-thri             cell-thro
  00000000000002724459  00000000000002741605
  cell-dsci             cell-dsco
  00000000000000000000  00000000000000000000
〜略〜
   05/06/27_15:03:47 ABC01DE3 FG2HIJK1

------------------------------------------------------------------------

上記内容と同等のものが計20万行あり、20万行の中から数字の連続した部分
(上の例では、0000000000や00000.00、00000000000000000000など)を抜き出すことを目標にしています。
しかし、ファイルサイズが重いせいか、パターンマッチをするまでのファイルの読み込み処理
に、非常に時間がかかっています。(ブラウザで読み込み結果を表示するのに2,3分かかる)
また、以下の環境とソースで行っています。

【サーバ環境】
・windowsNT 4.0
・PC 日立 FLORA 310(DL9) 330(DC9) 128Mメモリ
・サーバソフト AN_HTTPD Ver1.42m


【読み込み処理ソース】
if (!open(TXT, "+<$txtfile")) {
  &print_error("ファイルが開けません");
} else {
  @txt=<TXT>;
  close(TXT);

  foreach $eachtxt (@txt) {   
    if ($line1 =~ /[^a][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/i
      or $line1 =~ /[^a][0-9][0-9][0-9][0-9][0-9]\.[0-9][0-9]/io){ #マッチする行の検索
     〜〜配列へ挿入処理:省略〜〜
   }    
  }
}

サーバーがしょぼいのは重々承知ですが、スペック向上できない環境にあります。
この環境下で、高速に読み込み&高速パターンマッチを行う別の手段があれば、
ご教授をよろしくお願いします。

【習熟度】初めて

回答者 しあわせのツボ  [削除]  投稿日 2005/7/12(火) 15:15:54
まず、実メモリが128MBしかないのに20万行を
@txt = <TXT>;
と一括してメモリに読み込むのはやめましょう。直接
foreach (<TXT>) {
で回せばメモリは1行分しか消費しませんし、読み込みを待つこともありません。

次に正規表現。
[^a] は必要ですか?
数字だけを検索したいならiオプションは不要なので外した方が速そうです。
「10桁の数字」は「¥d{10}」(¥は半角)で表せます。同様に00000.00は「¥d{5}¥.¥d¥d」で可。
速度に関係するかはわかりませんが、[0-9]を並べるよりは良いかも。
質問者 dreamerYK  [削除]  投稿日 2005/7/12(火) 15:47:01
早速の回答ありがとうございます!!

パターンマッチの[^a]は、すみません、他のマッチに使用している例でした。

ご指摘の件ですが、
foreach(<TXT>){ でやってみたところ、若干ですが読み込み速度が向上したような気がします。
(計ったわけではないですが、、、)

ところでこの場合だと、ファイルハンドルをopenしたままforeachで処理しているので、
最初のユーザーがこのファイルハンドルをopenした後、次のユーザーが同処理に入った場合、
ファイルロックを使用していないのでファイルが壊れたりしないでしょうか?
(windowsは確かflockが使えないですよね?)



回答者 しあわせのツボ  [削除]  投稿日 2005/7/12(火) 17:52:30
ファイルが壊れるのは書き込みが関係する時です。
読んで表示するだけなら壊れません。
(と言うか@txt=<TXT>;も十分に長時間openしてるような(苦笑))

サーバが非力だとわかっているなら、読ませるファイルが巨大にならないよう分割するとか、
配列に溜め込まずに1行抽出するたびに表示して体感が速くなるようごまかすとか、
処理を高速化する以外の方法も考える必要があるでしょうね。
質問者 dreamerYK  [削除]  投稿日 2005/7/13(水) 09:18:32
こんにちは。
ご回答ありがとうございます。

そうですね、既に配列に読み込むだけでだいぶopenしてますね(笑)
読み込み時はファイル壊れないんですねぇ。。。
勉強になります!

とりあえず、もう少しいろいろ工夫してみようと思います。
また行き詰ったらこの板に書き込ませてもらいます!
しあわせのツボさん、丁寧なご回答ありがとうございました!

このページは終了したので返信(回答)は書きこめません
 


Web裏技