- ベストアンサー
もっとスマートに書きたい
テンプレートファイルがあり、そこにデータファイルから読み取ったデータを表示しようと思っています。 表示しようとしているデータは テーブルでセルがいくつかあるものです。 作ってみたのですが、もう少しスマートにかけないでしょうか。 データ: 1 2 3 4 5 テンプレート: <table> <!-- スタートする。カッコ内はセルの個数 --> <!--_START(4)_--> <tr> <td><!--_CONTENTS_--></td> <td><!--_CONTENTS_--></td> <td><!--_CONTENTS_--></td> <td><!--_CONTENTS_--></td> </tr> <!--_END_--> </table> プログラム: # @sample にテンプレートデータ # @data に データが入っています。 $kazu = @data; $flag = 0; foreach (@sample) { if (/<\!--_START\((\d+)\)_-->/) { $flag = 1; $sell = $1; } elsif (/<\!--_END_-->/) { $flag = 0; } elsif ($flag) { push(@kurikaesi,$_); } elsif (!$flag and $sell) { for($i=0;$i<$kazu;$i+=$sell) { $j = 0; @a = @kurikaesi; foreach $kuri (@a) { if ($kuri =~ /<\!--_CONTENTS_-->/) { $kuri =~ s/<\!--_CONTENTS_-->/$data[$i+$j]/g; print $kuri; $j++; } else { print $kuri; } } } $sell = 0; print; } else { print; } } 尚、テンプレートファイルの書式はこだわっていませんが、プログラムを分からないデザイナーに通すことを念頭においています。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
パっと見、スマートっぽいけど、効率とかは自信ないです。 前提として2点ばかり仕様変更。 ・テンプレートは配列に格納せずに一つの変数に全体を格納しておく。(→$template) ・開始を示すコメントにセル数は入れない。 単純に <!--_START_--> としておく。 $template =~ s/<!--_START_-->(.*?)<!--_END_-->/&data_replace($1,@sample)/se; # ↑この1行で 以下の関数の呼び出しと置換を行います。 sub data_replace{ my $orginal_temp = shift; my @data = @_; my $result; my $temp = $orginal_temp; foreach $dat(@data){ if($temp !~ /<!--_CONTENTS_-->/) { $result .= $temp; $temp = $orginal_temp; } $temp =~ s/<!--_CONTENTS_-->/$dat/; } $temp =~ s/<!--_CONTENTS_-->//g; $result .= $temp; return $result; }
その他の回答 (4)
- yuuki0229
- ベストアンサー率70% (33/47)
geオプションと合わせ置換先で配列操作(破壊)を行うとスマートになることがあります。 my $template = join '', @sample; $template =~ s/<!--_CONTENTS_-->/shift @data/ge; START~END間という条件を実現するには#1さんのように 内側の文字列を置換でサブルーチンに渡す方法がシンプルになりそうです。
お礼
アドバイスをありがとうございます。 置換をうまく使えばシンプルにできそうですね。 他の回答者の方の方法も参考にしてもっと修行に励みます。
- SE-1
- ベストアンサー率57% (26/45)
# こんなんどうでしょう。 my @data = qw/1 2 3 4 5/; my ($template,$num); open IN, "< template.txt"; { local $/; $template =<IN>; } close IN; $num = $1 if ($template =~/<!--_START\((\d)\)_-->/); $template =~ s/<!--_CONTENTS_-->/$data[$_]/ for (0..$num-1); print "$template\n";
お礼
ご回答ありがとうございます。 残念ですが、テストをしたところ、5番目が出てきませんでした。 どうやらSTART(4)の数字分しか書き出さないようです。 ずいぶんシンプルになったと思ったのですが、ちょっと工夫すれば使えそうではあります。 今後つかえる機会があれば使ってみたいと思います。
- noboru2000
- ベストアンサー率33% (47/140)
<!--_COUTENTS_--> の箇所が順次 @data の内容になればいいだけなら (<!--_START(4)_--> や <!--_END_--> は無視して) こうすればいいと思います。 my $n = 0; for (@sample) { ++$n if (s/<\!--_CONTENTS_-->/$data[$n]/); } 但し @data には丁度ぴったりの要素が入っていないといけませんが。
お礼
ご回答ありがとうございました。 実は書き忘れていましたが、 @dataの内容は増減する可能性があるので、回答いただいたような手は使えないのです。 条件が足らずに申し訳ございませんでした。
- steel_gray
- ベストアンサー率66% (1052/1578)
#1です。 テンプレートのミスがあると無限ループに陥る可能性があるので、 sub data_replace の foreachの前あたりに次の1行を足しておいてください。 return 'TEMPLATE ERROR' if($orginal_temp !~ /<!--_CONTENTS_-->/);
お礼
ご回答ありがとうございます。 かなりスマートになりました。 やっぱりやり方次第でこのようにできるのですね。 もっと修行が必要だと思いました。