• ベストアンサー

ファイルから読み込んで配列へ

PerlでCGIスクリプト(掲示板もどき)を作成しています。 配列の操作がうまくいかず、ご教授頂きたいと思います。 <やりたい事> 1.ブラウザ上のフォームからの入力を、カンマ区切りでテキストファイルに追記して保存。 2.そのテキストの一部を使ってHTMLで表を作る。 <実際の作業> 1.フォームからのデータはcgi-lib.plで連想配列として受け取り、unshiftでテキストファイルへ追記する。 &ReadParse; #フォームからデータを受け取る $o=$in{'name'}; $p=$in{'mail'}; $q=$in{'title'}; $r=$in{'comment'}; open(IN,"xxx.txt"); @tmp1=<IN>; close(IN); #1件1行として新規データを追加する unshift (@tmp1,"$oo" , "," , "$pp" , "," , "$qq" , "," , "$rr","\n"); open(OUT,">xxx.txt"); print OUT @tmp1; close(OUT); 2.xxx.txtのデータを読み込んで、1列目(name)と3列目(title)だけを使った表を作る。 データを読み込む時点でつまづき、先に進めません。 <テキストファイルの例> 1行目:a,b,c,d 2行目:e,f,g,h 3行目:i,j,k,l 以下同様 <症状> print @tmp1;とすると、a~lの全てのデータが表示される。 $tmp1[0];とすると、(a)のみ表示される。 $tmp1[1];とすると、カンマ(,)が表示される。 $tmp1[2];とすると、(b)が表示される。 <質問> 一つの行(配列)に対して2回繰り返す処理(nameとtitle)と、行単位で繰り返す処理(1行目、2行目…)を合わせればいいのだろうと思っていますが、どうすればいいのかわかりません。 気分的には↓こんな感じです。 foreach { "行の処理" foreach { "列の処理" } } そもそも、区切り文字であるカンマが、配列に格納されている時点で失敗しているのかな?とも思っています。 宜しくお願いします。 なお、不足している情報がありましたら補足いたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

> unshift (@tmp1,"$oo" , "," , "$pp" , "," , "$qq" , "," , "$rr","\n"); ここがやはりちょっとおかしいですね。 本来は unshift @tmp1, "$oo,$pp,$qq,$rr\n"; このようにすべきだと思います。 こうすれば一行につき一件のデータとなります。 > 2.xxx.txtのデータを読み込んで、1列目(name)と3列目(title)だけを使った表を作る。 この場合も上記のようにしていれば簡単です。 一行につき一件のデータで、そのデータがカンマ区切りになっているわけですから、 open IN, "xxx.txt"; my @tmp1 = <IN>; close IN; my $HTML = "<table>\n"; $HTML .= "<tr><th>name</th><th>title</th></tr>\n"; for (@tmp1) { chomp; my @data = split /,/; # ←これでカンマ区切りのデータが配列に格納されます $HTML .= "<tr><td>$data[0]</td><td>$data[2]</td></tr>\n"; } $HTML .= "</table>\n"; print "Content-Type: text/html\n\n"; print $HTML; exit; となり、$data[0]と$data[2]でテーブルを作って下さい。

ka-kichi
質問者

お礼

ありがとうございます。 unshift (@tmp1,"$oo" , "," , "$pp" , "," , "$qq" , "," , "$rr","\n"); を unshift @tmp1, "$oo,$pp,$qq,$rr\n"; に修正したところうまくいきました。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

デフォルトでは @tmp1 = <IN>; の直後では $tmp1[0] の値は "a,b,c,d\n" になっていないとおかしいはずです. 特殊変数で影響するのは $/, $,, $" くらいかな. ただ, 本当にこのコードでやってるなら入力そのものは間違っていないはずです. あと気になるのが, この「<症状>」というのが「どの時点で表示させたものか」ですね. どこで表示させたかがわからないので, この症状だけ見せられても問題解決には全然使えないです. 問題が生じるなるべく小さなコードを載せておいてくれればいいんですが.... ついでにいえば, 「1件 1行」とするなら「1行 = 配列の 1要素」とするのが安全じゃないかな. この unshift はちょっと疑問.

ka-kichi
質問者

お礼

ありがとうございます。 unshift (@tmp1,"$oo" , "," , "$pp" , "," , "$qq" , "," , "$rr","\n"); を unshift @tmp1, "$oo,$pp,$qq,$rr\n"; に修正したところうまくいきました。

  • tthe_mine
  • ベストアンサー率46% (19/41)
回答No.1

@tmp1 = <IN>; としたならば $tmp1[0] には "a,b,c,d\n" が入っていると思うのですが、、もしかしたらグローバル変数で挙動を変えられたかも知れません。 "perldoc perlvar" というコマンドで Perl にあらかじめ定義されている変数一覧とその説明を見ることが出来ます。本当に @tmp1=<IN>; で $tmp1[0] に1行目が入っていないのならば、これを探すと設定するべき変数が見つかると思います。 これだけではヒントにならないと思うので、サンプルコードを書いておきますね。(インデントは消えてしまうのですね。。。) <入力(hoge.txt)> a,b,c,d e,f,g,h i,j,k,i <コード> open(IN, "hoge.txt"); @lines = <IN>; close(IN); $i = 0; foreach $line (@lines) { print ++$i; @cols = split(/,/, $line); foreach $col (@cols) { print "\t$col"; } } <出力> 1 a b c d 2 e f g h 3 i j k i

ka-kichi
質問者

お礼

それぞれの処理をサブルーチンに分けていたせいもあるかもしれません。 ご提示のコードでうまくいきそうな気配がしてきました。 ありがとうございました。