Perlのエラーの意味を教えて

[上に] [前に] [次に]
中島 [E-Mail] [HomePage] 1998/01/20(火) 19:31:20
"アンケート用CGIを作るには??"で質問した中島です。
Web裏技でcgiをGetして、少し改造を加え、
現在、会社(^_^;)のSunでデバッグ中です。
でも、あるエラーが全然取れません。
しかも、全然改造してないところなのに、、、。
[parse error in file an.cgi at line 154,next 2 tokens ") keys"]という
エラーメッセージが出てきますが、どういう意味なのでしょうか。
また、エラーメッセージの一覧が見れるサイトはありますか??

B-Cus 1998/01/20(火) 19:52:00
とりあえず、どこをどう改造したのかがわからないと
なんとも言えません。

> [parse error in file an.cgi at line 154,next 2 tokens ") keys"]

要は文法エラーです。

> しかも、全然改造してないところなのに、、、。

まぁ、ありがちなことですけど、
セミコロンを忘れてないですか?
[]や{}、()、""、''などの整合はきちんととれていますか?

> 現在、会社(^_^;)のSunでデバッグ中です。

元のソースとdiffを取ってみればどうでしょう。

miyasiro [E-Mail] 1998/01/21(水) 22:25:46
keys の直前に ) があるのが気になって、an.cgi を覗いて来ました。
keys が使われているのは、115 行目の下の行だけなのですが、
  foreach (sort { $ans{$b} <=> $ans{$a} } keys %ans) {
ここでは、keys の前は } になってます。この辺は大丈夫なのでしょうか?

>元のソースとdiffを取ってみればどうでしょう。
なるほど、diff を使えば、意図しない書き換えを検出できますね。
ところで、Windows95 で使える(又は、long file name を扱える)
diff ってあるんでしょうか?

中島 [E-Mail] [HomePage] 1998/01/22(木) 11:31:35
miyasiroさん。ご指摘の件ですが、私の打ち間違いのようです。
(an.cgiは、” $ans{$a} } keys”でした。)
(コピー&ペースト)ができなかったので、自分で打ったときに、間違えたようです。
ご迷惑おかけしました。
結局のところ、もう一度、元ネタを持ってきて、改造しなおしたら、エラーがなくなりました。
でも、まだ完全には動いていません。

改造個所は、POSTのデータを$bufferに書き込むところのあとに、

for($k=0,$buffer=~/regist$k=/,k++)
    {$file = './an$k.dat/;
    $an_title= $k;
   }
という、データの格納場所を、元のhtmlから選べるように、変更しました。
色々と調べた結果、改造した$fileは、正確に動いていることが判明しましたが、
POSTされた文字列を、認識していないようで、
新規の投票ができない状態です。

疑いたくなかったんですが、どうしようもなく元ネタを調べてみたのですが、
「Web裏技」にある投票用フォームとアンケート用とを比べると、
$first dateと$last dateを算出する部分が、異なるのですが、
これはバグなのでしょうか、、、。

あーー、もうどこを直せば動くのか、検討もつきません。
本当に、疑いたくないのだけど、改造無しの状態で動くかどうか、試して見ます。

では、、、。

B-Cus 1998/01/22(木) 14:02:04
何をおっしゃっていらっしゃるのかわかりません。

・どういうCGIを持ってきて
・どういう機能を追加したくて
・どこをどう変更したんでしょう????

> $first dateと$last dateを算出する部分が、異なるのですが、

これが問題なのですか?

> POSTされた文字列を、認識していないようで、

それともこれが問題?

中島 [E-Mail] [HomePage] 1998/01/22(木) 16:36:13
失礼しました。
>・どういうCGIを持ってきて
「Web裏技」(http://www.ask.or.jp/~rescue/)のアンケート用フォーム(WebAN)
(an.cgi)を持ってきました。

>・どういう機能を追加したくて
いくつかのページから、別々のアンケートを取る為に、データ保存先の
$fileをPOSTで渡した値から選択するよう変更しました。
(Defaultは、$file = './an.cgi' でした。)

>どこをどう変更したんでしょう????
元のhtmlファイルの
<input type=radio name="regist" value="項目1">項目1<br>

を<input type=radio name="regist1" value="項目1">項目1<br>
に変更しました。

an.cgiの$ENV{'CONTENT_LENGTH'}を$bufferに入れる

if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
else { $buffer = $ENV{'QUERY_STRING'}; }

という文の直後に、
for($k=0,$buffer=~/regist$k=/,k++)
{$file = './an$k.dat/;
$an_title= $k;
}
を追加し、
$file = './an.dat';を削除しました。

以上が変更点です。

> $first dateと$last dateを算出する部分が、異なるのですが、
すみません、あまり問題ではありません。
たぶん、ここが間違っていても動きますが、
とりあえず、有識者のご意見をお聞かせください。

an.cgiでは、
if ($lines[($accesses - 1)] =~ /(.*)\,(.*)/) {

   $first_date = $1;
      ($clock,$day) = split(/ /,$first_date);
      ($hour,$minute,$second) = split(/:/,$clock);
      ($month,$mday,$year) = split(/:/,$day);

   $first_date = "$year年$month月$mday日 $hour時$minute分";
}

if ($lines[0] =~ /(.*)\,(.*)/) {

   $last_date = $1;
      ($clock,$day) = split(/ /,$last_date);
      ($hour,$minute,$second) = split(/:/,$clock);
      ($month,$mday,$year) = split(/:/,$day);

   $last_date = "$year年$month月$mday日 $hour時$minute分";
}

と記述されているのに、対して、
アンケート用フォームの高機能版である、
投票用フォーム(WebVote) vote.cgiでは、

if ($lines[0] =~ /\[(.*)\] (.*)/) {
   $first_date = $1;
      ($clock,$day) = split(/ /,$first_date);
      ($hour,$minute,$second) = split(/:/,$clock);
      ($month,$mday,$year) = split(/:/,$day);
   $first_date = "$year年$month月$mday日 $hour時$minute分";
}
else { $first_date = 0; }

if ($lines[($accesses - 1)] =~ /\[(.*)\] (.*)/) {
   $last_date = $1;
      ($clock,$day) = split(/ /,$last_date);
      ($hour,$minute,$second) = split(/:/,$clock);
      ($month,$mday,$year) = split(/:/,$day);
   $last_date = "$year年$month月$mday日 $hour時$minute分";
}
else { $last_date = 0; }

となっており、
if ($lines[($accesses - 1)] =~ /\[(.*)\] (.*)/) {
の値が、入れ替わっていることに気がつきました。
プログラム自体を理解できていないせいもあり、
何故、このように、書き換えられているかが、理解できていません。
どちらも正しいのでしょうか??

> POSTされた文字列を、認識していないようで、
恐らく、問題なのは、これだと思います。

素人目には、
文字コード変換と、データ保存を行うサブルーチンである、
sub registが動いていないように、見えます。
もう少し、調べてから、ご意見を伺いに来ます。

何を聞いていいか、わからない状態ですので、、、。

B-Cus 1998/01/22(木) 16:57:48
詳細な説明ありがとうございます。

まだよく読んでないんですけど、これ本当に動いてます?
なんか文法的にまずい(ように見える)ところがちらほら
ありますが。

> for($k=0,$buffer=~/regist$k=/,k++)

これ、OKでしょうか? forは、普通for(;;)ですよね?
for (,,)で動いてます? あとk++は$k++としなくて大丈夫ですか?

> $file = './an$k.dat/;

これも ''が対応していないし、''で囲むと$kの値が展開されません。

とりあえずこの部分は

$buffer =~ m/regist(\d)/;
$file= "./an$1.dat/";
$an_title = $1;

でどうですか?

あと、コマンドラインから実行できる環境なら(SUNのworkstationですよね?)、
いろいろなところにprint文を仕込んでおいて、

% setenv REQUEST_METHOD GET
% setenv QUERY_STRING 'name=regist1&value=koumoku1'
% ./an.cgi

とかやってデバッグしてみてはどうでしょう?


B-Cus 1998/01/22(木) 17:10:55
追加。

> $file= "./an$1.dat/";

これ、ファイルですよね? なら

$file= "./an$1.dat";

ですね。

中島 1998/01/22(木) 17:46:22
B-Cusさん、たびたびすみません。
実は、改造部分は、家においてあって、
「確か、こんな感じ、、、。」と書いてみましたが、
かなり適当だったようです。

家に、帰ってみてみないとわかりませんが、
for文の中は、;に、$fileは、'./an$k.dat';としてあるような気がします。

また、上記のプリント文を埋め込んでのデバッグを今から
やってみます。

どうも、お忙しいところ失礼しました。

中島 1998/01/22(木) 18:13:02
結果報告
an.cgiのヘッダ部で、$ENVの値を以下のように記述し、実行したところ、

$ENV{REQUEST_METHOD}=POST;
$ENV{CONTENT_LENGTH}='name=regist1&value=ABC';

以下のように、またもや文法エラーが出ました。
プロバイダでは、出なかったのですが、
PerlのVersionが違うのでしょうか??
それとも、$ENVを埋め込んでは、だめですか??

nakaji [160]an.cgi >ans
parse error in file an.cgi at line 120, next 2 tokens "} }"
parse error in file an.cgi at line 135, next token "if"
Execution of an.cgi aborted due to compilation errors.

B-Cus 1998/01/22(木) 18:14:35
> 実は、改造部分は、家においてあって、

できればこういうときは
 http://foo.com/~bar/an-org.txt(元のan.cgi)
 http://foo.com/~bar/an.txt(変更したan.cgi)
などと2つのURLを示していただけるとわかりやすいです。


で、正確にはどう書いたのかわからないのにあれこれ考えても
仕方ないのですが、他に間違いがないと仮定すると…

forの最初のループでは $k==0 なのだから、 $buffer 中に
regist0 という文字列がない場合、そのままループを抜けて
しまうんじゃないでしょうか。

結局 $fileも $an_title も未定義のまま、になってしまうと
思います。

B-Cus 1998/01/22(木) 18:29:54
> それとも、$ENVを埋め込んでは、だめですか??

これでOKです。

> プロバイダでは、出なかったのですが、
> PerlのVersionが違うのでしょうか??

プロバイダでは動いたんですか…。
それなら perl5 を使ってみるのも手ですね。
/usr/local/bin/perl5.003 とかありませんか?

あとオリジナルの an.cgi を動かしてみてください。

% diff an.cgi(変更したファイル) an.cgi.org(オリジナルのファイル)

とすれば2つのファイルの相違を表示してくれます。
それを見て、自分が書き加えたところに文法ミスがないか
調べてみてください。

中島 1998/01/22(木) 19:02:36
上が、Originalの実行結果です。

PerlのVerSionは、4.019でした。
5.004をdownloadして試してみます。

B-Cus 1998/01/22(木) 19:36:23
foreach (sort { $ans{$b} <=> $ans{$a} } keys %ans) {
問題はこの行ですね。

perl4.019では動きませんでした。perl5.002、perl5.004では
動作を確認しました(というかjcode.plがないって怒られて止まった)。

miyasiro 1998/01/22(木) 21:22:40
ラクダ本の翻訳第1版によると(P556)sort BLOCK LIST は 4.019 以降で使えるようです。
ただ、BLOCK中の最後の文の末尾のセミコロンが省けるのは、4.035 以降なので、
 foreach (sort { $ans{$b} <=> $ans{$a}; } keys %ans) {
とする必要があるのではないでしょうか

miyasiro 1998/01/22(木) 21:45:41
すいません、B-Cusさんは、単に
foreach (sort { $ans{$b} <=> $ans{$a} } keys %ans) {
の行に問題があると仰ってるだけで、sort BLOCK LIST に問題があると
言ってるわけではないですね。
とにかく、$ans{$a}の後にセミコロンを入れれば、 4.019 でもエラーは出ない
んじゃないのかな、ということです。
それから、$first_date と $last_date の問題は、たとえ間違いであったと
しても、表示が逆になるだけで、動作には影響しないと思います。

B-Cus 1998/01/22(木) 22:16:33
> とにかく、$ans{$a}の後にセミコロンを入れれば、 4.019 でもエラーは出ない
> んじゃないのかな、ということです。

はい、確かにセミコロンを入れると4.019で動きました。

ところで、perl4でもこういう書き方できたんですね〜。知らなかった。
僕はラクダ本の「任意の順番でソートするには」ってのを
そのままつかって、

sub mysort{ $list[$a] <=> $list[$b]; }
foreach ( keys %array ){ push(list,$_); }
&mysort $list[1..$#list];
# ↑うろ覚え。この通りやっても絶対動かないはず。

みたいなことをやってました。勉強になったっす(^-^)

中島 1998/01/22(木) 22:16:59
今、プロバイダのcgiをアップしました。
http://www2s.biglobe.ne.jp/~t_nakaji/Major/an.txtです。
-/Major/Term1.htmlに投票用フォームがあります。
sort Block Listを直したけれど、まだ、動いていません。
もう少し、調べてみます。

B-Cus 1998/01/22(木) 22:22:33
EOF;→last; かな? 後は文法的な間違いはないはずです。
# それともperlの機能としてEOFってのがある?


匿名希望 1998/01/22(木) 22:33:35


中島 1998/01/22(木) 22:35:30
このサイトでEOFがあるのを知って書いたのですが、、、。
とりあえず、last;にしてみました。
、、、。変化なし。

匿名希望 1998/01/22(木) 22:39:19


B-Cus 1998/01/22(木) 22:43:04
えっと、動かないというのはperlの文法エラーという意味ではなく、
アルゴリズム的にうまく動かないということですよね?

例えば for($k=0,$buffer=~/regist$k=/,k++){} をコメントアウトして、
$file='./an1.dat';$an_tutle="1"; などと決めうちしてみるとか、
printfデバッグをするとかして、動作が怪しい部分の範囲を狭めて
いってみましょう。

あと、もちろんオリジナルのCGIはちゃんと動くんですよね?

> このサイトでEOFがあるのを知って書いたのですが、、、。

へー知らなかったです。探してみよっと。

中島 1998/01/22(木) 22:49:56
今、気付いたのですが、私の手元で172行目に、
   $h = @REG;

   foreach $reg (@REG) {

      $value = "$date\,$reg\n";
      unshift(@lines,$value);
   }

というのが、ありますが、
$hって、この前にも、後にも、使ってません。
また、$regは、ここに書いてある2つだけです。
$regに値が入っていないことになりますが、
こういう場合、どうなるのでしょうか??

匿名希望 1998/01/22(木) 22:55:38


匿名希望 1998/01/22(木) 22:56:16


B-Cus 1998/01/22(木) 23:00:45
んっと、そういうふうに気づいたところを手あたり次第に見ていっても
いいのですが、効率が悪いです。

オリジナルのCGIが動くなら、中島さんの書き方が悪いし、
オリジナルのCGIが動かないなら、web裏技が悪いです。
# 「悪い=うまく動かない原因である」ってことで

原因を切り分けていかないと、いつまでたっても動きませんよ。

$hはよーわかりませんが、
foreach $_ (@REG) {
 $value = "$date\,$_\n";
 unshift(@lines,$value);
}
と書き換えてみると、$_はここにしかでてきませんが、意味はあります。
この説明でわかりますよね。

# この匿名希望さんの書き込みはいったい…(^^;

匿名希望 1998/01/22(木) 23:02:28


中島 1998/01/22(木) 23:08:30
B-Cusさんに言われて、オリジナルで試してみました。
結果は、Server Errorで、
/Major/an.cgi: Exec format error
となりました。
配付される位だからと思っていたのですが、甘かったようです。
「Web裏技」に問い合わせてみることにします。
どうも、皆さん、御迷惑おかけしました。

匿名希望 1998/01/22(木) 23:10:29


匿名希望 1998/01/22(木) 23:11:20


匿名希望 1998/01/22(木) 23:11:39


匿名希望 1998/01/22(木) 23:11:55


匿名希望さんへ 1998/01/22(木) 23:12:39
あんた何??

匿名希望 1998/01/22(木) 23:19:22


匿名希望 1998/01/22(木) 23:19:55


匿名希望 1998/01/22(木) 23:23:20


匿名希望 1998/01/22(木) 23:26:55


miyasiro 1998/01/23(金) 01:25:36
お気を悪くせずに読んで頂きたいのですが、どうも中島さんの作業は、順序が
バラバラなような気がします。まずは、とにかくオリジナルをちゃんと動かす
ことが先決でしょう。オリジナルのスクリプトに所定の変更を施し、所定の
手順でサーバに設定して(またはローカルで)、ちゃんと動くことが確認され
てから、改造に取り掛かるべきだと思います。この際、疑うとか疑わないという
ことは、関係ありません。また、「配付される位だから」というのも意味があり
ません。プログラムをすべての環境で動作保証するなんてことは不可能です。
ということで、まずはじっくり落ちついてオリジナルを動かすことから取り
掛かって下さい。その上で、またお役に立てることがあれば、私もお手伝い
させて頂きます。

中島 1998/01/23(金) 02:20:06
miyasiroさん、B-Cusさんには、何を言われても仕方がないと思っております。
tohohoからcgiを持って行って、2度程動かした実績があった為か、
「なんだ、俺でもできるじゃないか」と、有頂天になっていた面もあります。
「チャレンジ ザ パール」なんて考えて、ここを改造すれば、
動くだろうと思い始めたら、エラーが続出し、
エラーの”理由”ではなく、”意味”を聞くつもりが、
こんなことになってしまいました。
本当に、確認もせずに、こんなに時間を裂いて頂いて申し訳ありませんでした。

miyasiro 1998/01/23(金) 03:06:19
>>中島さん
最初は誰でもそうだと思います。まず、オリジナルを動かすことから、
一歩ずつやって行きましょう。手順を確認した上で、それでもオリジナルが動作
しないなら、サーバのperlのバージョンや出力されたエラーメッセージなどを
教えて下さい。

>>B-Cusさん
>僕はラクダ本の「任意の順番でソートするには」ってのを
>そのままつかって、
 @sortdata = @array[sort mysort 0..$#array];
みたいな感じで「配列を加工したキーでソートする」ものですね。
私は、こっちを知りませんでした。
こういう処理をする必要がある場合は、多分 sub mysort の中で、毎回
配列要素を加工するような効率の悪いコードを書いていたと思います。
こちらこそ、いろいろ勉強になります。

中島 1998/01/23(金) 23:04:19
[[解決]]
やっと動きました。
まず、正式版は、フォーマットエラーで動いていないことが判明しました。EUCにしても、S-JISにしても、Server Errorとなりました。現在も、オリジナルを使うとフォーマットエラーになります。
改行コードも、LFなのに、、、。
ところが、前回ある程度動いていた改造版を、もう一度UPし、アンケート用フォームの見本で試したところ、突然動作し始めました。
何故かと、原因を調べた結果、
オリジナルの
     if ($name eq "regist" && $value ne '') { push(@REG,$value); $tnx = 1; }
     elsif ($name eq "view") { return; }
の部分が、改造の為に動いていないことが、判明し、これを、以下のように書き換えました。
     if ($name = ~/regist/ && $value ne 'view') { push(@REG,$value); $tnx = 1; }
     elsif ($value eq "view") { return; }
これで、現在、正常に動いています。
どうも、お騒がせしました。

ところで、オリジナルが動かないフォーマットエラーって、
改行コードや、漢字コード以外に、何が考えられますか??
御意見お聞かせください。

miyasiro [HomePage] 1998/01/24(土) 01:48:56
う〜ん、どうも、まだうまくコミニケーションが取れないようです。
とりあえず、an.cgiをうちのホームページに設置してみました。
オリジナルのままで(ただし、HTML出力にperlのバージョンを
書き出す文を追加しました)、正常に動作してます。
上の HomePage にありますんで、覗いてみて下さい。

miyasiro 1998/01/29(木) 22:07:48
終わったようなので、後始末します。
上のメッセージの HomePage の URL は削除しました。
それで、結論ですが、オリジナルの an.cgi は、
www2s.biglobe.ne.jp 上の
#! /usr/mesh/bin/perl5(version 5.003)
#! /usr/mesh/bin/perl(version 4.036)
#! /usr/local/bin/perl(version 4.036)
で問題なく動作しました。
ただし、version 4.019 では、B-Cus さんに確認して頂いたように、
 foreach (sort { $ans{$b} <=> $ans{$a}; } keys %ans) {
の行の ; が必要なようで、それ以前の version では、少なくとも
 sort BLOCK LIST
の書式が使えません…ということで。

中島 1998/01/31(土) 16:57:48
[[解決]]
回答遅れて申し訳ありませんでした。
えー、現在は、オリジナルは正常に動いております。
前回の書き込みのcgiは、会社のSunで、動作を確認したものを、
会社から、BinHexで自宅に送ったものを使ったのですが、
どうもこの添付したのがいけなかったのか、
未だに、Format Errorが出ます。
で、もういちど、「Web裏技」から入手して、上記と同じ変更(アドレスとか。)を加えたものは、動きました。
なんで、添付したものが動かなくなったのか、原因を見つけてから投稿しようと思ったのですが、未だに、全然わかりません。
ということで、長い間、お世話になりました。
では、では。

miyasiro 1998/02/02(月) 18:27:20
同じサーバーなのになぜオリジナルが動作しないのか不思議だったのですが、
了解しました。改造の方、ガンバッて下さい。
ただ、質問するときは、今度はもう少し正確な情報をよろしくね。> 中島さん

[上に] [前に] [次に]