はじめまして

CGIを学んで1ヶ月の者です。
実は、仕事で少し面倒な依頼を受けて困っております。
内容はCSV形式のデータをPerlで読み取ってそれを
HTMLのテーブルに流し込むスクリプトなのですが、
慣れていないので思考停止をして進みません。

具体的なCSVデータの例ですが、

10,果物,りんご,ringo.html,ぶどう,budou.html,ばなな,banana.html,10,野菜,かぼちゃ,kabotya.html,なす,nasu.html,きゅうり,kyuri.html,魚,まぐろ,maguro.html,さけ,sake.html,10,肉,牛,usi.html,麺,ラーメン,ra-men.html,そば,soba.html,うどん,udon.html

まず、先頭に10があり、これは分類の区切りを示すヘッダーです。
次に果物でこれは、分類名です。
次にりんご、これは分類詳細名です。
つぎにringo.htmlでこれは分類詳細名のリンク先アドレスです。

このようなデータの並びですが、各分類と詳細項目は変動しますので
このテーブルのあるWEBページを毎回読み直す必要があります。

どうのようにしたらよいのでしょうか。
お助けください。

このQ&Aに関連する人気のQ&A

A 回答 (13件中1~10件)

たびたび登場です。



前回紹介したのは基本的な間違いがいっぱいありました。
あと「全角スペース」がよけいにあってはいけないこともわかりました。
この掲示板では、全角スペースを入れないと左詰になってしまい、
みにくなりますが、
コピーした後半角スペースかタブで調節して見やすくしてください。

この前の失敗
1. 「$i」とすべきところを「i」としている箇所が多い
2. 「$title_color」を突然書いていた→「bgcolor=$title_color」
3. よけいな全角スペースがあった→すべての全角スペースを無くしました

以上をふまえて、hoomaさんのスクリプトを集成し、
実際に試してみてちゃんと実行できました。
どうぞお試しあれ。
htmlの表示部分から修正スクリプトを載せておきます。

------------------------------------------
print "Content-type:text/html\n\n";
print "<html>\n";
print "<body>";

$title_color = "#6699cc";
print "<table>\n";
foreach $output (@lines){
@table= split(',',$output);
for($i=0;$i+1<$#table;$i=$i+2){
if($table[$i] == 10){
print"<tr><td bgcolor=$title_color>$table[$i+1]</td></tr>\n";
next;
}
if($table[$i] == 20 && $table[$i+2] == 30){
print"<tr><td><a href=$table[$i+3]>$table[$i+1]</a></td></tr>\n";
$i = $i+2;
next;
}
if($table[$i] == 20 && $table[$i+2] != 30){
print"<tr><td>$table[$i+1]</td></tr>\n";
next;
}
}
}
print"</table>";
print "</body>\n";
print "</html>\n";
------------------------------------------
    • good
    • 0
この回答へのお礼

ありがとうございました。
お礼がしたいのでメールアドレスを教えてください。

お礼日時:2001/04/27 17:04

こんにちは。



#リストの細分化
foreach $output (0..$#lines){
 @table= split(',',$lines[0]);
}

これですと、
せっかくforeach文を使って、
データの数だけ繰り返し処理しているのに、
その中では、全く同じ事しかしていませんので、
一行のデータの処理しかできません。

foreach $output (@lines){
 @table= split(',',$output);
}
とすると、@linesの数だけforeach文で処理が繰り返され、
一行ごとのデータが$outputに入り、
その$outputのデータを毎回切り分けていますので、
@tableには新しい情報が入っていきます。
でも(多分)どんどん上書きされてしまうので、
このループの中で表示もしてしまった方が良いです。
(まあ別の変数にデータを入れてもいいんですが)

とりあえず全てのデータを改行させながら表示させるのでしたら

foreach $output (@lines){
 @table= split(',',$output);
 for($i=0;$i<$#table;$i++){
  print "$table[i]<BR>\n";
 }
}
とすると、もともとのデータが細切れになり改行されて全て表示されるでしょう。
まだ規則的でないデータが@tableにストリームとして入っているだけですので、
テーブルを作成する段階ではないので、もう少し処理が必要です。

10,分類,20,詳細名,30,リンク先,20,詳細,20,詳細名,30,リンク先,名,30,リンク先
10,分類,20,詳細名,30,リンク先
10,分類,20,詳細名,30,リンク先,20,詳細,20,詳細名,30,リンク先,名,30,リンク先

このデータで僕が表を作るとすると、
--------------------------------------------
$title_color = blue;

print "<table>\n";
foreach $output (@lines){
 @table= split(',',$output);
 for($i=0;$i+1<$#table;$i+2){
  if($table[i] == 10){
   print"<tr><td $title_color>$table[i+1]</td></tr>\n";
   next;
  }
  if($table[i] == 20 && $table[i+2] == 30){
   print"<tr><td><a href=$table[i+3]>$table[i+1]</a></td></tr>\n";
   i = i+2;
   next;
  }
  if($table[i] == 20 && $table[i+2] != 30){
   print"<tr><td>$table[i+1]</td></tr>\n";
   next;
  }
 }
}
print"</table>";

--------------------------------------------
といった感じになります(ただし動作未確認)。

この回答への補足

こんばんは

いただいたソースを元に付け合せてPCのアパッチで試しても、うまくでないので

ACTIVE perlで -CWをつけてチェックしたところ下記の警告がでました。

Unrecognized character \201 at test1.pl line 21.

これってなんですか、

それと何か記述がおかしいでしょうか。
--------------------試したソース----------------
#!C:\perl\bin\perl
#ファイルの読み込み
$file = "sample2.csv";
open(DB,"$file");
@lines = <DB>;
close(DB);

#改行データ除去
chomp($lines);


print "Content-type:text/html\n\n";


print "<html>\n";

$title_color = "#6699cc";

print "<table>\n";
foreach $output (@lines){
 @table= split(',',$output);
 for($i=0;$i+1<$#table;$i+2){
  if($table[i] == 10){
   print"<tr><td $title_color>$table[i+1]</td></tr>\n";
   next;
  }
  if($table[i] == 20 && $table[i+2] == 30){
   print"<tr><td><a href=$table[i+3]>$table[i+1]</a></td></tr>\n";
   i = i+2;
   next;
  }
  if($table[i] == 20 && $table[i+2] != 30){
   print"<tr><td>$table[i+1]</td></tr>\n";
   next;
  }
 }
}
print"</table>";

print "</body>\n";
print "</html>\n";

補足日時:2001/04/26 21:39
    • good
    • 0

>foreach $output (0..$#lines){


>@table= split(',',$lines[0]);
>}
>上記のリスト細分化の部分は今のところ1行しか処理できないようになっていますが、

そりゃ行番号をしちゃってますから。
リファレンス本で foreach の構文を調べてください。
ところでこれだと @table が毎回上書きされちゃって、
後半のforeachでは最後の @tableしか出力してないのでは?
    • good
    • 0

>データの中に識別子を付けた場合、後で、取り除くための記述はどうしたらいいでしょうか。



$hoe ~= s/^10_//;
です。
    • good
    • 0

>10,分類,20,詳細名,30,リンク先,20,詳細20,詳細名,30,リンク先,名,30,リンク先



それだったら
10_A,20_B,30_C,20_B,30_C~
って感じに「データの中に判別子を埋める」ほうがいいです。
「今“10”だったから次のデータは“分類”だ」よりも
「頭が“10”だからこのデータは“分類”だ」のほうがソースが
見やすくなります。頭の「10_」とかは後で消せばいいわけです。

しかし本当は「位置でデータ種別を判別させる」ほうが簡潔だし
処理も早くなります。なぜに下記のような表計算リスト的なデータ
にしないのでしょうか?
A,B,C,D
A,B,C,D

A,B,C,D
,,C,D
↑でもいいですから、とにかく「項目の位置は固定」させたほうが
いいです。実際にくんでみればわかります。

この回答への補足

ありがとうございます。
danyさんのおっしゃるとおり、データの中に識別子を付けた場合、後で、取り除くための記述はどうしたらいいでしょうか。

補足日時:2001/04/26 16:49
    • good
    • 0

No.4の返答への返答です。


この返答で私が書いた「HEAD TYPE NAME ADDR」というのは

10,果物,りんご,ringo.html,ぶどう,budou.html,ばなな,banana.html,10,野菜,かぼちゃ,kabotya.html,なす,nasu.html,きゅうり,kyuri.html,魚,まぐろ,maguro.html,さけ,sake.html,10,肉,牛,usi.html,麺,ラーメン,ra-men.html,そば,soba.html,うどん,udon.html

というデータよりも

10,果物,りんご,ringo.html
10,果物,ぶどう,budou.html
~略~
10,麺,そば,soba.html
10,麺,うどん,udon.html

「1データ1行で、1行は同じ項目数」という感じに元データを作り直して
もらったほうがいいということです。

で、今気付いたんですが、
A,B,C,D,A,B,C,D,A,B,C,D,
って感じに項目数は同じなのかと思いました。
A,B,C,D,C,D,C,D,
なんですね。これだとNo2、No.3のサンプルはまったくのゴミです。^^;

提示された形式だと、「中に入っているデータがどんな形式なのか」を
調べないといけないし、もしデータに規則性がないなら判断のしようも
ありません。それとも「10」という数字がデリミタ(分割指定子)ですか?

いずれにせよ、もし私がこの仕事をやるハメになったとしたら
「こんなデータではやってられません。元データを作り直してください」
ってとこからスタートします。^^;

この回答への補足

たびたびありがとうございます。
やはりデータを見直したほうがいいですね。
それで、データの種別をはっきりわかるようにするために
10,分類,20,詳細名,30,リンク先,20,詳細20,詳細名,30,リンク先,名,30,リンク先
10,分類,20,詳細名,30,リンク先
10,分類,20,詳細名,30,リンク先,20,詳細20,詳細名,30,リンク先,名,30,リンク先
のようにしたほうが作りやすいのかなと思いこういう形式で現在考えてます。
これでしたら、楽になりますでしょうか。

補足日時:2001/04/26 15:23
    • good
    • 0

多次元配列って使ったことないんですが、



@datasに各行のデータが入っているとして、

print "<table>\n";
foreach $data (@datas){
 $dataを細切れにする
 細切れデータから表を作る
}
print "</table>\n";

のような感じではできないでしょうか?

この回答への補足

現在、わたくしが出来ているところまで掲載いたします。
#!C:\perl\bin\perl
#ファイルの読み込み
$file = "sample.csv";
open(DB,"$file");
@lines = <DB>;
close(DB);

#改行データ除去
chomp($lines);

#リストの細分化
foreach $output (0..$#lines){
@table= split(',',$lines[0]);

}

foreach $i(0..$#table){
print $table[$i],"\n";
$i+=1;
}

それで、問題なのですが、上記のリスト細分化の部分は今のところ1行しか処理できないようになっていますが、これを全行処理させたいのです。
それとも、この部分をサブルーチンにして、
FOR文で繰り返して、行を変えながらサブルーチンに飛ばしたほうがよいのでしょうか。
その場合、最終行を見分ける方法がわかりません。


どうしたらよいでしょうか。

補足日時:2001/04/26 16:40
    • good
    • 0

どうもこんばんは。


再び登場です。

>ある分類がポッカリなくなったり、ある分類内の詳細名が増減することを想定しないといけないもので、やっかいに感じてます。

hoomaさんは変動するデータや、項目の変動が激しいことを気にしていらっしゃるようですが、
自作のCGIをいくつか遊びで作ってきた経験から言わせてもらいますと、
そういう変動するデータのためにこそCGIが有効ではないかと思います。
htmlでは固定的な表現しかできませんが、プログラムを使うことの利点は
アクセスする度に変動的な表現ができることではないでしょうか?

項目が変動した場合にもばりばり動かすCGIを作ろうと思っているなんて
個人的には楽しそうでうらやましいです(笑)
僕も仕事でそういうの任されてみたいです(^^)

どのように変動データに対応するかは
CGIプログラムの問題ではなくて
アルゴリズムの問題だと思います。

まあPerlのプログラミングとして、
どのようにデータを加工するのがやりやすいか
などを気にする必要もあるので、
アルゴリズムとプログラムは同時に考えた方がいいですけどね。
ある程度経験のある人なら、
元データがこういう形の方が扱いやすいと言うこともわかると思います。

お礼を見ていると、「これ以上答えてもらうのは悪い」という感じが伝わってきましたが、
そんなことありませんので、もっと具体的な困っている箇所をあげてくだされば、
一つずつ進んでいけるのではと思いますよ。

あと、特にUNIXの知識なんて必要ないような気がしますが。

この回答への補足

あたたかいお言葉ありがとうございます。
他の補足でも説明しましたが、
http://www.niigata-megumi.co.jp/rdn/
「取扱品目」のページのようなレイアウトで
表はCSVで流し込みをするということです。

とあるシステム系の会社のサイト構築を頼まれて、デザインを主にやってます。
そのなかで、CGIがたくさん絡んできており、ほとんどが外注に出して出来上がってますが、クライアントは一方ついてから、今回のようなスクリプトを用意してくれと言ってきたのでGW前に納品しないといけないので切羽詰っています。

今、私が自分で確認してできているスクリプトは
表(中身は空)をHTMLに書き出すCGIだけです。

CSVを読み込んで、配列にいれて細切れにして、データの種別」を判断し、テーブルに書きだすというものが
使い慣れていないのでアドバイスをいただいても「あーそうか!」と言って実行に移せないのです。
こわがっているのかもしれません。

でも、明日は1日perlと闘えそうなので、じっくり取り組んでみます。

補足日時:2001/04/24 22:38
    • good
    • 0
この回答へのお礼

お礼ではのですが、補足をしたくても
入れる場所がないのでこちらで失礼します。

いろいろ試して、ようやく読み込んだCSVデータを配列に入れてsplitをかけて、細切れにすることはできました。(ただし、1行だけ)
そこで、教えていただきたいのですが、全行を多次元配列などにしてsplitをかけるにはどうしたらいいでしょうか。
foreachなどで試しましたが、うまくいきません。

お礼日時:2001/04/26 12:05

一行にすると &conv2 のような余計な行程が必要になってくるから


やめたほうがいいです。ExcelやAccessの画面をイメージしていただけると
わかると思いますが、

HEAD TYPE NAME ADDR
HEAD TYPE NAME ADDR
HEAD TYPE NAME ADDR

という感じに並ぶのが一番効率がいいです。
TYPEが存在しない場合は空欄に、ひとつの項目に複数存在する
場合は「/」とか、“絶対使われない文字”で区切るのがいいです。

head(TAB)type(TAB)name,name2(TAB)addr
みたいな感じにTABで区切り、項目内をさらに分割するときは
「,」みたいな。

# 現実逃避終了したので以降の回答がニブくなると思われます(笑)

この回答への補足

すみません教えていただきたいのですが、
@TYPE = qw( HEAD TYPE NAME ADDR );
という記述がありますが、例えばデータが 10,果物,りんご,ringo.htmlとなっていた場合に、
HEAD TYPE NAME ADDRにはどう記述すればよいのでしょうか。HEADは10 のような気がしますが、他の場合変わってしまうのでどうしたらいいのかわかりません。

補足日時:2001/04/26 11:53
    • good
    • 0

質問にあったのが「決まった順番が横並びに連続する。

しかも数は変動」
という前提で作ってみたものです。「&conv1」→「&conv2」にする
以外は同様。

あとTABLEにするのなら「<tr></tr>」が必要というのを忘れてたので
それも追加しました。

# 変換タイプ2
# ====================
sub conv2{
 my $line = shift;          # 渡された行の内容
 @lines = split( ',',$line );    # 「,」で分割して配列へ
 foreach $i ( 0 .. $#lines ){    # 0番目から配列の最後まで繰り返す
  $x = (($i+1) % ($#TYPE +1)) - 1;
  if( $TYPE[$x] eq 'HEAD' ){    # 以降、番号に対応した項目で変換処理
   ~HEAD項目に対する変換処理~
   }elsif( $TYPE[$x] eq 'TYPE' ){
   ~TYPE項目に対する変換処理~
  }elsif( $TYPE[$x] eq 'NAME' ){
   ~NAME項目に対する変換処理~
  }elsif( $TYPE[$x] eq 'ADDR' ){
   ~ADDR項目に対する変換処理~
  }
  $output .= '<tr>' if $x == 0;   # 最初のやつなら<tr>追加
  $output .= $lines[$i];       # 出力用変数に追加書き
  $output .= '</tr>' if $x == -1;  # 最後なら</tr>追加
 }
}

# ====================
>$x = (($i+1) % ($#TYPE +1)) - 1;
↑ちょっとわかりにくいかもですね。^^;
何番目の項目かというのを判別するには、項目数で割った余り(%)を
求めればいいのですが、番号が「0」から始まるので「+1」してます。

「$#TYPE」は「@TYPE」の最後の添え字、この場合「3」が入ってます。
項目数は「4」ですがやはり「0」から始まるので「+1」してます。

1番目 … ((0+1)%(3+1))-1 = 0
2番目 … ((1+1)%(3+1))-1 = 1
3番目 … ((2+1)%(3+1))-1 = 2
4番目 … ((3+1)%(3+1))-1 = -1
5番目 … ((4+1)%(3+1))-1 = 0
6番目 … ((5+1)%(3+1))-1 = 1
7番目 … ((6+1)%(3+1))-1 = 2
8番目 … ((7+1)%(3+1))-1 = -1
9番目 … ((8+1)%(3+1))-1 = 0

4番目は「3」を出したいところですが、Perlは配列の何番目かを
指定するとき「-1」すると、後ろから、つまり最後のものを取得
してくれるのでこのままにしてます。他の言語ではダメかも。^^;

~変換処理~のところは
$line[$i] =~ s/^(.+)$/<td>$1<\/td>/;
もしくは↓のほうがスッキリ
$line[$i] =~ s|^(.+)$|<td>$1</td>|;

ぬ、とてもPerl歴一ヶ月の人に教えるようなものではないですね…。^^;
まぁこういう方法もあるよ程度に留めておくといいかも。

この回答への補足

本当にお世話になっております。
最終的には下記のレイアウトで表示させたいのですが、
http://www.niigata-megumi.co.jp/rdn/
トップページから「取扱品目」のリンクをクリックしてください。
そうすると表が出てくると思います。
そのようなレイアウトの表にCSVデータを流し込んで、
リンクさせていきたいと考えております。
この表内に流すCSVデータですが、
ある分類がポッカリなくなったり、ある分類内の詳細名が増減することを想定しないといけないもので、やっかいに感じてます。
CSVのレコードフォーマットはやりやすいように考えてもいいとクライアントから言われています。

補足日時:2001/04/24 18:47
    • good
    • 0
この回答へのお礼

ありがとうございました。
後は、なんとか自力で考えていきます。

perlはUNIXの知識も必要になるので、
習得しずらいのかな感じてます。

お礼日時:2001/04/24 20:50

このQ&Aに関連する最新のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


このカテゴリの人気Q&Aランキング

おすすめ情報

カテゴリ