WEB相談室

Webページ作成に関しての何でも掲示板です。

タイトル:ファイルを読みこんで文字列置換

0:[投稿] atusi [2002/07/14 18:32 ][環境:WIN+IE WIN系+Perl]

ファイルを読み込んでただ書き出すのであれば
while(<FILE>) {print;}
とする方がforeach を使って配列に入れてから書き出すよりもメモリを食わない、と書籍で読んだのですが、

下のようにhtmlファイルを読み込んでパターンマッチをさせたい場合、
他の書き方で書けないでしょうか?

また、この場をお借りしてさらに2点ほどお尋ねしたいのですが・・・

追記@) top.gif やsite.gif などの置換させたい文字列が
一行に入っている場合と改行をはさんで存在する場合、と
分けて考えなくてはならないのでしょうか?

追記A) また、タグ打ちでは無く市販されているHTMLエディタを使用して
あるタグの途中に改行が入ることってあるのでしょうか?

皆様のお知恵を拝借したく存じます。
どうぞよろしくお願いいたします。

    # HTMLファイルを読み込む
    open(FILE,"<./template/preview.html") or errorPrint("can't open preview_html");
    eval{ flock(FILE,1)};
    @data = <FILE>;
    close FILE;
    
    # 一度スカラーに取り込む
    foreach (@data) {
        $html .= "$_";
    }
    

    # 置換を行う / 以外の区切り文字を使う
    $html =~ s#top.gif#./template/top.gif#;
    $html =~ s#site.gif#./template/site.gif#;
    $html =~ s#bottom.gif#./template/bottom.gif#;                
    
    print $html;


1:[回答] バギンズ [2002/07/14 23:19 ]

>メモリを食わない
HTMLファイルを読むだけならメモリは気にしなくてもいいと思います。

>top.gif やsite.gif などの置換させたい文字列が
>一行に入っている場合と改行をはさんで存在する場合、と
>分けて考えなくてはならないのでしょうか?
top.gif やsite.gif などだけであれば、途中の改行は気にしなくてもいいと思います。

>市販されているHTMLエディタを使用して
>あるタグの途中に改行が入ること
あります。
改行は表示上半角スペース分の空きができてしまう為、わざとタグの途中(属性と属性の間のスペース等)で改行するものがあります。
HTMLエディタの作りが悪いと言ってしまうとそれまでですが、以前IBMのホームページビルダーで作ったHTMLファイルではよく見かけました。(最近のバージョンは知りません)

># 一度スカラーに取り込む
joinする手も...


2:[回答] AA [2002/07/15 07:51 ]

一度スカラーに取り込む場合、

> # HTMLファイルを読み込む
>  open(FILE,"<./template/preview.html") or errorPrint("can't open preview_html");
>  eval{ flock(FILE,1)};
>  @data = <FILE>;
>  close FILE;
>  
>  # 一度スカラーに取り込む
>  foreach (@data) {
>      $html .= "$_";
>  }

は、かなり無駄なので、

open FILE, "template/preview.html" or errorPrint("can't open preview_html");
read FILE, $html, -s FILE;
close FILE;

や、

open FILE, "template/preview.html" or errorPrint("can't open preview_html");
$html = do { local $/; <FILE> };
close FILE;

などの方法がよいです。


3:[完了] atusi [2002/07/15 14:33 ]

ご教授どうもありがとうございました!!!

自分だけでは改善できなかった点、
気づきにくい点をご指摘頂いて本当にありがたく存じております。

どうもありがとうございました。


4:[質問] atusi [2002/07/18 22:16 ]

以前ご指導頂いた下のスクリプトですが、

open FILE, "template/preview.html" or errorPrint("can't open preview_html");
$html = do { local $/; <FILE> };
close FILE;

自分で調べて
$/    入力レコードセパレータ
local グローバル変数を局所化している($/ を局所的に変更する)
do    引数に取った式などを実行する

という所までわかったのですが、
何故 $html に値が入るのかがわかりません。

$html = do { local $/; <FILE> };

の一行の意味がわからないのです。

よろしかったらどなたか教えて頂けませんでしょうか???

勉強不足による稚拙なご質問をさせて頂き恐縮ですが、
どうぞよろしくお願いいたします。


5:[回答] ナン [2002/07/19 14:58 ]

$/は、入力レコードセパレータで、デフォルトでは、改行です。
で、local $/ をしているのは、そのセパレータをundefにしています。
で、そうするとファイル全体が読み込み対象になります。
で、<>演算子でファイル全体を読み込み、doで、それを$htmlに代入しています。

と、私は思いました。perlは、最近自信ない...。


6:[回答] やじうま1号 [2002/07/19 15:11 ]

$i = "text";

&text;

sub text{
    local $i;
    print "text",$i;
}

そこでテスト。
結果は
text
でした。
すなわち、ナンさんの解説の通りです。


7:[回答] R.M [2002/07/20 03:14 ]

補足

do { local $/; <FILE> }
が $html に入るべき内容を返すのは
do が最後に評価した式の値を返すからです
これだと <FILE> になります

これと同じことをやってるわけです
do {
 local $/;
 $html = <FILE>;
}

もしくは
$sep = $/;
undef $/;
$html = <FILE>;
$/ = $sep;


8:[回答] B-Cus [2002/07/20 19:05 ]

> $html = do { local $/; <FILE> };

わざわざわかりにくい書き方をしなくても、

 $html = join('', <FILE>);

でいいんじゃないかなぁ。


9:[回答] ミキスケ [2002/07/23 08:43 ]

>>8 改行を検索する必要があるから、のろくなるんじゃない?


10:[回答] ふじ [URL] [2002/07/23 14:21 ]

>> 9

ベンチマーク取ってみましたが、速度的には read 一発で済ませるのが
最速のようです。配列操作が入るとやっぱり遅くなる。

ちなみに、
$html = do { local $/; <FILE> };
よりも
{
   local $/ = undef;
   $html = <FILE>;
}
の方が3倍ぐらい速い。こっちならそんなに分かりにくくないんじゃないかと。
もしくは、
use English;
{
   local $INPUT_RECORD_SEPARATOR = undef;
   $html = <FILE>;
}
とか。

# 450行、100KBのテキストファイルで実験
use Benchmark;                                                                                  
use strict;                                                                                    
                                                                                               
timethese($ARGV[1], {                                                                          
   'join_array' => \&join_array,                                                              
   'read_once'  => \&read_once,                                                                
   'no_RS'      => \&no_RS,                                                                    
   'normal'     => \&normal,                                                                  
});                                                                                            
                                                                                               
sub join_array                                                                                  
{                                                                                              
   my $html;                                                                                  
   open(FILE, $ARGV[0]) or die $!;                                                            
   my @data = <FILE>;                                                                          
   close FILE;                                                                                
   foreach (@data) {                                                                          
       $html .= $_;                                                                            
   }                                                                                          
}
sub read_once                                                                                  
{                                                                                              
   my $html;                                                                                  
   open(FILE, $ARGV[0]) or die $!;                                                            
   read FILE, $html, -s FILE;                                                                  
   close FILE;                                                                                
}
sub no_RS                                                                                      
{                                                                                              
   my $html;                                                                                  
   open(FILE, $ARGV[0]) or die $!;                                                            
   $html = do { local $/; <FILE> };                                                            
   close FILE;                                                                                
}
sub normal                                                                                      
{                                                                                              
   my $html;                                                                                  
   open(FILE, $ARGV[0]) or die $!;                                                            
   $html = join('', <FILE>);                                                                  
   close FILE;                                                                                
}

join_array: 39 wallclock secs (37.80 usr +  1.77 sys = 39.57 CPU) @ 126.36/s (n=5000)
    no_RS:  3 wallclock secs ( 1.95 usr +  1.08 sys =  3.03 CPU) @ 1650.17/s (n=5000)
   normal: 40 wallclock secs (37.55 usr +  1.72 sys = 39.27 CPU) @ 127.32/s (n=5000)
read_once:  0 wallclock secs ( 0.11 usr +  0.51 sys =  0.62 CPU) @ 8064.52/s (n=5000)

回答(必須): 状態:

お名前(必須):

e-mail:

URL:




[戻る]

ChaichanPAPA's World