トップページ⇒php
981コメント390KB

くだすれPerl(超初心者用)2

■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん2008/03/03(月) 05:07:32ID:???
このスレッドは、他のスレッドでは書き込めない超低レベル、
もしくは質問者自身何が何だが分からない質問を勇気を持って書き込むスレッドです。
Perl使いが優しくコメントを返しますが、
お礼はPerlの布教と初心者の救済をお願いします。
0232nobodyさん2008/05/20(火) 04:28:46ID:???
>>231
私の環境ではエラーになっちゃったけど
物凄く参考になった
ありがとう
0233nobodyさん2008/05/20(火) 04:36:24ID:???
>>231
できました!
スペースの文字コードを半角スペースに変えたらエラーにならないで実行できました
見事に日本語になってます
ありがとうございました!
0234nobodyさん2008/05/20(火) 15:30:39ID:???
>>231をhtmlファイルで保存したいんだけどできない
すいませんまた教えてください

open(FH, '>>', "yahoolog001.html") or die "Cannot open content()!";
flock(FH, 2);
print FH qq|content()\n|;
0235nobodyさん2008/05/20(火) 16:51:57ID:???
>>234
231をyahoo_get.plとでも名前付けて保存して、
perl yahoo_get.pl > yahoo001.html
0236nobodyさん2008/05/20(火) 17:29:08ID:???
>>235何回もすいません
どうすればいいのか?
下記のような状況です

open(FH, '>>', "yahoolog001.html") or die "Cannot open yahoo001.html!";
flock(FH, 2);
perl yahoo_get.pl > yahoo001.html;

-----------------
Can't locate object method "perl" via package "yahoo_get" (perhaps you forgot to
load "yahoo_get"?) at yahoo-tes001.pl line 6.
0237nobodyさん2008/05/20(火) 18:28:08ID:???
>>235
スクリプト内に入れてやれよww

print FH encode('cp932',decode('utf8',LWP::UserAgent->new()->get('http://www.yahoo.co.jp')->content()));
0238nobodyさん2008/05/20(火) 18:38:22ID:???
>>236
違う違う、235のは、コマンドラインから実行するんであって、perlスクリプトの中に書くんではない。

>>234とか見てると、ファイルのオープンとかはあってるけど、
オブジェクトとか、クラスメソッドとかのことを良く分かってないようなので、
とりあえず一行で書けるのにしてみた。

それから、君は>>211や>>230と同じ人(?、かどうかは定かではないが)
コマンドプロンプトから実行してるなら、リダイレクトや標準出力、標準入力等についてもある程度は理解がないと。
(Perlではないんで、入門書とかにはあんまり書いてないか。でも基本ってか常識レベルなんで、
わかってないとこれからしんどいよ。逆にわかってくると、いちいちスクリプトの中でやらなくていいことが増えるんで
書くのが楽になるし、理解も深まる。)
0239nobodyさん2008/05/20(火) 18:42:43ID:???
wktk
0240nobodyさん2008/05/20(火) 21:15:41ID:???
>>237さん、>>238さん、御二方ともお忙しい中ありがとうございます
FH付けると何故かまた文字化けになってしまい苦戦していました
よくわかりませんがcp932を止めたら文字化けが亡くなりました
アドバイスのお陰で2つの方法で保存させることが出来ました
しかも昨日までは取得した最後の1024バイトしか表示されなかったのですが
ページ全部を取得できていますありがとうございました
↓スクリプトだけで保存でたソース
---------------
use LWP;
use Encode;
open(FH, '>>', "yahoolog001.html") or die "Cannot open yahoo_get.pl!";
flock(FH, 2);
print FH LWP::UserAgent->new()->get('http://www.yahoo.co.jp')->content();
↓コマンドラインから保存できたソース
--------------
use LWP;
use Encode;
print LWP::UserAgent->new()->get('http://www.yahoo.co.jp')->content();
ここからログインのテストしたいので
またお願いするかもしれませんが
その時はよろしくお願い致します
>>238さん
勉強方法詳しくありがとうございました
標準入出力の解説書なかなか見当たらないです
手持ちの解説書で標準入出力を解説しているのは
「perlデータマンジング」という本だけです
大変わかりやすく良書なのですが紙面の関係上さわり程度なのが残念です
何かお勧めの解説書があれば教えて頂ければ嬉しいです
ありがとうございました
0241nobodyさん2008/05/22(木) 14:07:57ID:???
お世話になります
httpsでログイン可能な簡易ブラウザサンプルどこかないでしょうか?
自分が調べたところ2001年にある雑誌が付録で付けていたようなのですが
絶版になり各方面探しても見当たりませんでした
やりたいことはhttps接続での送受信です
お心当たりのある方よろしくお願い致します
0242nobodyさん2008/05/22(木) 14:12:19ID:???
LPW
0243nobodyさん2008/05/22(木) 14:12:53ID:???
間違えた笑
LWP
0244nobodyさん2008/05/23(金) 20:25:12ID:VktSXUAF
sで一気にいくつかのものを変換する方法ありますか?
たとえるならあいうえおという文のあとおをかとこにおきかえたいんです。
0245nobodyさん2008/05/24(土) 02:20:54ID:???
trじゃダメなの?
0246nobodyさん2008/05/26(月) 19:32:51ID:???
どもお世話になります
あれから色々調べているんですけど
ログインや検索やセレクトメニューの選択やボタンクリックなど
具体的なサンプルってないですね
もしかしてperlで出来ないですか?
結局HACKER本買い捲ったんだけど
みんなHTMLの取得までなんですよ
そこからセレクトメニューを選んだりOKボタンをクリックするとか
できないんだろうか?
0247nobodyさん2008/05/26(月) 19:36:22ID:???
お前は何を言っているんだ
0248nobodyさん2008/05/26(月) 20:03:33ID:???
なんで?
perlでなんでも出来るって言ってたじゃないですか?
0249nobodyさん2008/05/26(月) 20:18:52ID:???
ネタですか?
0250nobodyさん2008/05/26(月) 20:35:06ID:???
>>248
もしかして>>196からの流れか?
ひょっとして画面が表示されて検索ワードが勝手に入力されてセレクトメニューが勝手に選択されてボタンが勝手に押されるとか
そういうのイメージしてる?
0251nobodyさん2008/05/26(月) 20:47:35ID:???
>>250
それそれ
それです!
perlで出来るんですよね?
今のところそのようなサンプル見当たらないんですよ
自動ソフトのスクリプトとかならOKボタンのクリックなどは
初歩の初歩インストール後5分後には覚えれるくらい簡単なんですけど
perlの場合参考になるような記述すら見当たらないんですよ
超凄いらしい解説本やオライリーのHACKシリーズやWEBシリーズを購入したんですけど
全然すごくない
OKボタンの1回すら出てこない
なんでもできないのですか?
0252nobodyさん2008/05/26(月) 20:54:44ID:???
それをやろうと思ったのはお前が最初で最後だと思うよ
0253nobodyさん2008/05/26(月) 21:12:52ID:???
>>252
なんでですか?
perlでは出来ないってことなの?
0254nobodyさん2008/05/26(月) 21:16:41ID:???
ちなみに自分はある自動ソフトで検索とか保存とか
WEB上での操作でやりたいことは大体教えてもらえましたよ
そのソフトを教えてくれる方たちはみんな普通にご存知でした
ただ遅いんですよorz
0.5秒で完結させたいんです
0255nobodyさん2008/05/27(火) 02:30:31ID:???
>>252
自分は>>198や>>201なんだけど、多分初めてじゃないと思うぞ(w)

>>253,254
君のやりたいことってのが、GUIのツールみたく目に見える感じで動いて行くってのなら多分ムリ。
(Tkとか使ったら無理やりにでもできるかも知れん。でも自分はGUI系はからっきしなんで、よくわからん)

そうでなくて、コマンドラインから、ブラウザで操作したことと同じ結果を得るってことなら可能。
どんな本や、どんなページ参考にしたかわからないけど、
ちょっと上の方に出てるLWPなんかの解説や、CPANのmanualなんかをじっくり読めば(リンクを少々辿らないダメだけど)、
検索フォームにワード仕込んだり、”OK”ボタンを押すってことにもたどりつきそうだけど・・・。
02562552008/05/27(火) 02:31:04ID:???
でもまあ、サンプルでも書いとく。
use strict;
use LWP;
use Encode;
use HTML::Form;

my $pwd = `cd` . '\\';
my $cmd = 'C:\Program Files\Internet Explorer\iexplore.exe';
my $url = 'http://google.co.jp/';
my $lwp = LWP::UserAgent->new('agent'=>'mozilla3.9');
my $word; my $out1 = '1.html'; my $out2 = '2.html';
$word = shift() or $word = 'Perl'; $word =~ tr/\r\n//d;
my $html = $lwp->get($url)->content();
open(O1,">$out1"); print O1 $html; close(O1);
system qq("$cmd" "$pwd$out1");
my $form = HTML::Form->parse($html,$url);
$form->value('q' => encode('utf8',decode('cp932',$word)));
$form->value('ie'=> 'UTF-8');
my $response = $lwp->request($form->click);
my $out2 = '2.html';
open (O2,">$out2"); print O2 $response->content(); close(O2);
system qq("$cmd" "$pwd$out2");

これを、例えばtest_search.plとでも保存して、コマンドラインから、
perl test_search.pl "検索したいキーワード"
で実行すると、最初googleのTopが表示されて、それを閉じれば、そのワード(なければ”Perl”)での
検索結果がIEで表示される。(無理やり、画面遷移っぽくなるように作った。)
モジュールや関数の詳細は、自分で調べてくれ。
0257nobodyさん2008/05/27(火) 03:14:05ID:???
また湧いたのか・・・
0258nobodyさん2008/05/27(火) 03:29:45ID:???
>>255さん
ありがとうございます
まさにそれなんです
GUIを使わないで送受信してみたいんです
お疲れのところわざわざサンプルまで作って頂き本当にありがとうございます!
頂いたサンプルを参考にログインとかもチャレンジしてみます
ありがとうございました
0259nobodyさん2008/05/27(火) 14:08:14ID:???
ブラウザのインターフェースに強引に割り込ませるのかと思ったわ
httpについて勉強するといいよ
0260nobodyさん2008/05/28(水) 00:14:16ID:T0EpbUiq
ググったら趣旨が違うのしかでないんですが、
ifで、たとえば$Aに\という文字列が含まれる場合、
\が含まれています。とするにはどうしたらいいんでしょうか?
if($A =~ \\)
{print "\\が含まれています"}
でいけますか?
0261nobodyさん2008/05/28(水) 02:23:14ID:???
if($A =~ /\\/)
0262nobodyさん2008/05/31(土) 01:19:07ID:???
$in{'ext'} = extfind($in{'orgname'}); if(!$in{'ext'} && $in{'upfile'}){ &error(202); }

この処理ってどういう意味なのでしょうか?
0263nobodyさん2008/05/31(土) 02:02:14ID:???
;
0264nobodyさん2008/05/31(土) 15:52:59ID:???
>>262
>$in{'ext'} = extfind($in{'orgname'});
サブルーチン(?) extfindの一番目の引数にハッシュ$in{'orgname'}の値をセットして
呼び出し、戻り値をハッシュ$in{'ext'}に代入。

>if(!$in{'ext'} && $in{'upfile'}){ &error(202); }
次にハッシュ$in{'ext'}の中の人が留守で、
尚且つハッシュ$in{'upfile'}の中の人が居る場合
恐らくエラーメッセージを表示するであろう
サブルーチンerrorの一番目の引数に"202"をセットして呼び出す。


ちなみに2行を一行にまとめると↓みたいになる
&error(202) if(!&extfind($in{'orgname'}) && $in{'upfile'});
02652642008/05/31(土) 15:54:58ID:???
戻り値をセットせなあかんから1行にまとめたら駄目だな・・orz
02662642008/05/31(土) 16:03:00ID:???
&error(202) if(!($in{'ext'} = &extfind($in{'orgname'})) && $in{'upfile'});

オリジナルと大して変わらんけどこうやればいけるか
スレ汚しスマソ・・
0267nobodyさん2008/05/31(土) 18:48:39ID:???
より、この処理ってどういう意味なのでしょうか?
という質問が出易くなりますな。
0268nobodyさん2008/05/31(土) 20:14:45ID:???
>>264
やっぱりperl難しいな・・・

http://sugachan.dip.jp/obsolete/snup/
拡張子合わずってログに記録したときは
ファイルをアップしないように改造しようかと
思ってるのだがなかなかできなくて。。。

$in{'ext'} = extfind($in{'orgname'}); if(!$in{'ext'} && $in{'upfile'}){ &error(202); }
を
$in{'ext'} = extfind($in{'orgname'}); if(!$in{'ext'}){ &error(202); }
に、しても普通にアップロードできてしまうし。。。どこがおかしい?
0269nobodyさん2008/05/31(土) 20:40:29ID:???
>>268
そこのアップローダの改造の質問 って前にもどこぞで見たなあ。
で「改造スレに行け」と言われてたハズだが?

ソースが好みじゃないのでやる気にならん。…改造スレ行けば?
0270nobodyさん2008/06/04(水) 08:35:22ID:???
perlで書かれたチャット掲示板みたいなCGIプログラムがあります
テキストエリアに文字を入力して、投稿ボタンを押すとregist.cgiに渡されて書き込まれる仕組みです
このregist.cgiはmessageとcountという2つの引数をとるみたいなのですが、
ブラウザからURL:/aaa/bbb/regist.cgi?message=test&count=1
とやっても書き込まれませんでした

ちなみにFirefoxのTemperDataで確認したリクエストとレスポンス上ではベーシック認証は使われていませんでした

最終的にはperlで自動的に書き込んでくれるプログラムを書きたいのですが、まずはperlでこのregist.cgiに投稿するにはどうすればいいか教えてください
0271nobodyさん2008/06/04(水) 10:11:46ID:???
postしてみろ
0272nobodyさん2008/06/04(水) 14:06:46ID:???
GETで投稿出来ちゃうと、2chにリンク貼られまくったときにw
0273nobodyさん2008/06/06(金) 23:21:44ID:???
sub getDirSize($)の($)ってどういう意味?
0274nobodyさん2008/06/07(土) 02:53:47ID:???
>>273
プロトタイプ。
$は引数としてスカラーしかとらないってこと。
02752732008/06/07(土) 08:37:38ID:???
>>274
thx
0276nobodyさん2008/06/13(金) 17:42:23ID:GNaVOr+f
UTF-8の16進コードを文字にしたいんですが、
pack('C*','0xe4','0xba','0xba')とやっても化けてしまいます。
どういう式を書けばいいのですか?
0277nobodyさん2008/06/13(金) 18:06:20ID:???
pack('C*',0xe4,0xba,0xba) だとどうなる?
0278nobodyさん2008/06/13(金) 18:32:03ID:???
>>277
ありがとうございます。できました。
裸のままでよかったのですね。
pack('H*','e4baba');
というのもあったみたいです。

今は10進→16進→文字なんですが、
10進から直接変換できますか?
0279nobodyさん2008/06/13(金) 18:37:43ID:???
0xがついてなきゃ10進だよ。
pack('C*',228,186,186) とか
10進の数字しかないならpack('C*','228','186','186') でも通るけどな。
0280nobodyさん2008/06/13(金) 19:26:54ID:???
ありがとうございます。
文字列との違いが判りました。

UTF-8のコード範囲を調べると
[\x00-\x7f]
[\xC0-\xDF][\x80-\xBF]
[\xE0-\xEF][\x80-\xBF][\x80-\xBF]
[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]
とあります。
これには他の言語も含まれているとおもいます。
先ほど教えていただいた変換で一覧を作ろうと思うのですが、中国語なども混ざってしまいます。
日本語のみの範囲はどのようなものなのでしょうか。
0281nobodyさん2008/06/13(金) 19:41:37ID:???
ttp://ja.wikipedia.org/wiki/Unicode
0282nobodyさん2008/06/13(金) 20:36:31ID:???
そういえば、日本語じゃなくても、
罫線とか利用している文字もありますね。
なかなか難しい。
0283nobodyさん2008/06/15(日) 14:13:18ID:???
postやgetじゃなくて、普通にページにアクセスしたときの条件分岐が作りたいのですが、
そんなことはできませんか?
0284nobodyさん2008/06/15(日) 14:29:37ID:???
Use of uninitialized value in concatenation (.) or string at main.cgi line 93.
このエラーの意味が分からないのですが、教えて頂けませんか?
0285nobodyさん2008/06/15(日) 20:40:23ID:???
>>283
もう少し詳しく
>>284
main.cgiというファイルの93行目で、連結の方法がおかしい。
0286nobodyさん2008/06/15(日) 22:45:56ID:???
>>284
>>285 =~ s/連結の方法がおかしい/未定義値を文字列として評価している/;

例えば $foo が undef の状態で "foo$foo" とか 'foo' . $foo とか。
0287nobodyさん2008/06/16(月) 09:05:17ID:???
おはようございます。

あるサブルーチンでファイルを扱おうとしています。
evalの中でopenしたファイルハンドルをエラー処理(if $@)で閉じるにはどうすればよいのでしょうか。
環境はperl5.8 use strictです。
0288nobodyさん2008/06/16(月) 10:45:47ID:???
http://pc11.2ch.net/test/read.cgi/tech/1208674881/514
より

#!C:/perl/bin/perl

open(IN,"example.log");
while(<IN>){
$i++;
if($i == 3){ $line .= "\t\t$_"; }
else{ $line .= "$_"; }
}
close(IN);

open(OUT,">example.log");
print OUT $line;
close(OUT);

print"Content-type:text/html\n\n";
print "変更完了";
0289nobodyさん2008/06/16(月) 10:49:36ID:???
http://pc11.2ch.net/test/read.cgi/tech/1208674881/511
より

#!C:/perl/bin/perl

open(IN,"example.log");
while(<IN>){
unless($_ =~ /hoge/){ $line .= "$_"; }
else{ $line .= "\n"; }
}
close(IN);

open(OUT,">example.log");
print OUT $line;
close(OUT);

print"Content-type:text/html\n\n";
print "消去完了";
0290nobodyさん2008/06/16(月) 13:00:09ID:???
>>288-289
せっかくお答えいただいたのにすみません。
私が知りたいのはスコープを跨ぐ場合の話です。

例えば、evalの中で宣言した変数をevalの外で使おうとすると、perlに叱られます。
ファイルハンドルの場合は叱られないのですが、これが作法に則った方法なのかわかりません。
0291nobodyさん2008/06/16(月) 14:31:35ID:????2BP(1)
案1)
my $fh = IO::File 〜とかopen my $fh〜等を使って
いちいち閉じなくていいようにする。

案2)
use IO::File;して
my $fh = *FH{IO};
$fh->close() if defined($fh) && $fh->opened();
0292nobodyさん2008/06/16(月) 16:00:58ID:???
>>290

失礼。他のスレッドへの返答でした。

http://pc11.2ch.net/test/read.cgi/tech/1208674881/519 への回答

# 変数が半角スペースで始まっていれば、半角スペースを先頭一個だけ消去
if($example =~ /^ /){ $example =~ s/ //; }
# 変数が全角スペースで始まっていれば、全角スペースを先頭から一個だけ消去
elsif($example =~ /^ /){ $example =~ s/ //; }

拙いですがどうですか?
0293nobodyさん2008/06/16(月) 16:05:48ID:???
>>292

修正です。

# 先頭の全角スペース、半角スペースの連続を削除
$example =~ s/^([\ \ ]+)//;
0294nobodyさん2008/06/16(月) 17:36:08ID:???
流れがよく分からんけど、
もうひとつファイルを用意して、
書き出して言ったらダメなの?

>>293
スクリプトとファイルの文字コードが同じならいいけど。
0295nobodyさん2008/06/16(月) 21:58:28ID:???
>>291
ありがとうございます。

お答えいただいた案1がしっくりきたので、この方式で行きます。

またよろしくお願いします。
0296nobodyさん2008/06/17(火) 10:38:26ID:???
>>294

すいません、超未熟でした。
0297nobodyさん2008/06/18(水) 00:25:23ID:Mmy0x8n6
perlで、
print "あ";
で一秒待ってから
print "い";
を実行する方法ってありますか?
localtimeで受け取って1秒過ぎるまでwhileで空白を書き続けるってのも考えたんですが・・・
負荷がかかりそうなんで。
0298nobodyさん2008/06/18(水) 01:19:02ID:???
sleep 1;
0299nobodyさん2008/06/19(木) 06:37:25ID:???
select undef,undef,undef,1;
0300nobodyさん2008/06/19(木) 10:35:29ID:???
$| = 1;
0301うっとりハムちゃん2008/06/20(金) 15:05:12ID:nHevfWAE
すいません、教えてください。

掲示板に書き込まれた内容に URLが含まれていた場合、
自動的にリンクになるようにしたいのですが、
簡単に追加する方法等がありますか?
よろしくお願いします。
0302nobodyさん2008/06/20(金) 15:20:25ID:???
URLかチェックして一致したらAタグ追加する。
正規表現 perl URL とかでググれば例が出てくると思う
0303nobodyさん2008/06/20(金) 22:01:17ID:???
>>301

$_ =~ s/([^=^\"]|^)(http\:\/\/[\w\.\,\~\-\/\?\&\+\=\:\@\%\;\#\%\*]+)/$1<a href=\"$2\">$2<\/a>/g;
0304nobodyさん2008/06/20(金) 22:29:00ID:???
…メタ文字じゃない文字をエスケープして意味あんの?
文字クラス中のエスケープは更に酷い。
0305うっとりハムちゃん 2008/06/21(土) 03:14:25ID:k6DOaEg8
皆さんレスありがとうございます。
>303 さんの記述を一行足すだけではダメですよね?
例えば $comment 内に書き込まれた中から抜粋する際は
それを指定する必要などはありますか?
0306nobodyさん2008/06/21(土) 07:47:06ID:???
minibbsあたりのソースで見ましたね>余計なエスケープ
0307nobodyさん2008/06/21(土) 17:19:06ID:???
>>305
print &autolink($comment);

sub autolink {
my $text = $_[0];
$text =~ s{(s?https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)}{<a href="$1">$1</a>}g;
return $text;
}

参考: Perlメモ
http://www.din.or.jp/~ohzaki/perl.htm#httpURL
0308うっとりハムちゃん2008/06/21(土) 19:10:28ID:???
できました!!!
とても親切で、どうもありがとうございました!!
助かりました! m(_ _)m
03092972008/06/21(土) 21:40:03ID:etCJxH2B
遅くなりました。
ありがとうございました。
0310nobodyさん2008/06/23(月) 09:49:20ID:???
遅くなったのは、教わったとおりにsleepしてから書き込んだから
0311nobodyさん2008/06/23(月) 20:42:58ID:???
だれかボスケテ。

---post_data.cgi---
use CGI::Lite

#read(STDIN,$buff,$ENV{'CONTENT_LENGTH'});
$param = CGI::Lite->new()->parse_form_data('POST');

print "Content-Type: text/plain\n\n";
print "$buff\n";
for (sort(keys(%$param))){
    print "$_ = " . $param->{"$_"} . "\n";
}
つう、なんの変哲もないファイルを書いて、これに、

---test.js---
function reQuested_files( data,method,fName,async,callback){
    var r_obj = crHttpReq();
    r_obj.onreadystatechange = function(){
    if(r_obj.readyState == 4){ callback(r_obj); }
    }
    r_obj.open( 'POST','post_data.cgi',async );
    r_obj.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    r_obj.send( 'a=abcdeFG&b=123.4567&z=zzz' );
}

から、javascriptのXMLHttpRequest(所謂ajaxってやつ)でのPOST送信のテストをしたんだけども・・・、
03123112008/06/23(月) 20:43:29ID:???
これの戻り値を、
function callback_function(rs_obj){
    var res  = rs_obj.responseText;
    alert( decodeURI(res) );
}

で、alert表示させた場合の結果がおかしい。

具体的にゆうと、これでIEからの送信だと、alertに
a = abcdeFG
b = 123.4567
z = zzz

と、正確に(期待したとおりの)結果が返って来るんだが、最近出たばかりのFirefox3でやると、
結果alertになにも表示されない。

これjavascriptのせいかなと思って色々調べてみたんだが、まだはっきりとわからない。
けど試しに、上のレスのスクリプトで、コメントアウトしてる read() 部分を有効化させてやると、
どちらも同じ結果になる。(a=abcdeFG&b=123.4567&z=zzz)

つまりこれは、STDIN(POSTデータの実体)は入ってるのに、CGI::Lite->parse_form_data('POST')
で、なぜか狐3の時だけ、正常にパースされてない様なんだけど、どうなのかな? っと思って聞いてみた次第です。
(Web鯖のエラーログにも、値をParse出来ないみたいなerrorが出てました。)

これから、Javascript関係のスレにも行ってみようかと思うんですが、
とりあえず上記のPerlコードに、問題がないか確かめたかったんです。(問題ないですよね?)
ちなみに、htmlのフォーム上から、action="post_data.cgi" method="POST" で送った時は、IE,FFとも問題ありません。
0313nobodyさん2008/06/23(月) 22:23:59ID:???
スレチなきもするが、非同期通信の呼び出し方法はブラウザごとに違うよ。
つ prototype.js
03143112008/06/24(火) 05:32:07ID:???
>>313
ありがとうございます。そうなんですよ。
実はFF3リリース日に、別件でsync,ansyncについての挙動の違い(F1.5,2.0と3.0で)に遭遇しまして、
いろいろ調べてなんとかそちらの方は解消しました。今回のもやはり同様の理由かなぁ〜と思っていましたが、
原因判明しました。結論から言うと、javascript側だけの要因ではなく、Perl側にも原因があることがわかりました。
(割合は、とりあえず半々とゆうことにしときます。)

>>311の、post_data.cgiを、CGI::Liteだけでなく、CGI.pmにしてみたり、直でSTDINから読み込んだり、
同様のスクリプトをphpで実行したりして、原因突き止めました。

まず、IE6,7、Firefox1.5,2.0,3.0で、POSTしたデータそのものについては、1byteの違いもなかったんですが、
受け側により、処理の仕方に差異があるようでして、これの違いは、送り側の"Content-Type"にありました。

具体的には以下
03153112008/06/24(火) 05:38:53ID:???
送り側    ※     実際の送信されるリクエストヘッダ
IE 6       なし   (なにも無し)
IE 6       あり   application/x-www-form-urlencoded
IE 7       なし   (なにも無し)
IE 7       あり   application/x-www-form-urlencoded
FF 1.5    なし   application/xml
FF 1.5    あり   application/x-www-form-urlencoded
FF 2.0    なし   application/xml
FF 2.0    あり   application/x-www-form-urlencoded
FF 3.0    なし   application/xml; charset=UTF-8 ※1
FF 3.0    あり   application/x-www-form-urlencoded; charset=UTF-8 ※1
(※. setRequestHeader('...')の有無)
(※1.表示しているカレントページのcharsetに関わらず、UTF-8で固定のようです。)
03163112008/06/24(火) 05:48:29ID:???
モジュール  ヘッダ(#1)  パース(※)
CGI::Lite       なし    出来る
CGI::Lite       #2  出来る
CGI::Lite       #2 #8   出来ない
CGI::Lite       #3  出来ない
CGI.pm      なし    出来る(※)
CGI.pm      #2  出来る
CGI.pm      #2 #8   出来る
CGI.pm      #3  出来る(※)
Apache2::Reuest なし    出来ない
Apache2::Reuest #2  出来る
Apache2::Reuest #2 #8   出来る
Apache2::Reuest #3  出来ない
php(おまけ) なし    出来ない
php     #2  出来る
php     #2 #8   出来る
php     #3  出来ない
03173112008/06/24(火) 05:56:14ID:???
ずれまくりですいません。

>>315
については、一応RFCでは、フォームからの入力をPOSTする時には、必ず"application/x-www-form-urlencoded"
をヘッダに含めなくてはならないとなっております。
また、上記と似たような検証をしていたサイトがあって(といっても、そちらは1年ほど前の時点での調査でしたが)、
このようにブラウザごとに差異があるので、XHRでPOSTメソッドをリクエストをする時は、
setRequestHeader('application/x-www-form-urlencoded')が ”必須” になるとも書いてありました。
一応ここまでが、Javascript側の要因です。

>>316
Perlに関しては
#1 $ENV{'CONTENT_TYPE'}の値(ブラウザからのContent-Type リクエストヘッダ)
#2 application/x-www-form-urlencoded
#3 その他(text/plainなど)自前のLWPとHTTP::Request::Commonで、適当なリクエストヘッダをでっちあげて確認した。
#8 charset=UTF-8
※.一般的なデータ取得関数を使って、変数に値をセットできるかどうか。例:CGI::Lite->parse_form_data()、CGI.pm->Vars()、
phpだと$value=$_POST{'name'}など。CGI.pmだけは特殊で、x-www・・・以外のどんな場面であっても、
"POSTED=name=value&name=value&name・・・・"とゆう形で取得できる。
03183112008/06/24(火) 05:57:06ID:???
とゆうことで注目するのは、CGI::Liteだけ、"application/x-www-form-urlencoded"の後ろに"charset="が付くと、
データ取得関数でデータを取得出来ないことと、他の一般的なモジュールで本来取得できないハズの
Content-リクエストヘッダ無しの場合でも、普通にデータを取得出来てしまえるところに、混乱した原因があるようだ。

ちなみに、上の調査の追記としては、read(STDIN.$var,$ENV{'CONTENT_LENGTH}) を使えば、
全てのパターンでデータの取得が可能。(パースとデコードは全て自分でやらないといけないですが)
しかしながら、これを各moduleのデータ取得用関数の前に持ってくると、その後の取得関数が全てコケる。(値なしになる。)
また、取得関数の後に持ってきても、その前の関数の成功失敗に関わらず、データを取得できない。(phpでは未確認)
(多分STDINに対するファイルポインタが、終端まで行ってしまっためだと思う)

今までお恥ずかしいながら、ajaxに限らず、ほとんどCGI::Liteメインで書いてきた。(GET,POSTの違いも大して意識してなかった)
それにモジュールのロードが軽い(自機での測定で、CGI.pm比約四倍早い)し、自分には、CGI.pmは機能が豊富すぎて、
使いこなせてないって思ってた。

だけど、今後のこと(新しいブラウザ対応とか)を考えるに、どうもCGI::Liteだけではやっていけなくなってしまいそう。
まあ、最終リリースからもう五年もメンテされてないんで、早く乗り換えろよってのはもっともな話だとは思うけど・・。
なんかくやしいなぁ。

313さんへ、
自分はJavascriptについては、prototype.jsやjQueryなどの外部ライブラリを使ったことがなくて、余り詳しくもないんだけど、
これからはどうしようかと検討中です。でも今回の件に限れば、自分が受け側をCGI::Liteで利用したのが原因で
多分外部ライブラリ使ってても同じ現象に遭遇してたと思います。そんな時は余計に、原因の究明に困ったかも知れません。

とゆうことで、長々と失礼しました。同じような問題で悩んでる人がいたら、参考にして下さい。
0319316貼り直し2008/06/24(火) 06:17:21ID:???
mod   (#1)     (※) 
CL     なし     出来る 
CL     #2       出来る 
CL     #2 #8   出来ない 
CL     #3       出来ない 
Cp     なし     出来る(※) 
Cp     #2       出来る 
Cp     #2 #8   出来る 
Cp     #3       出来る(※) 
AR2   なし     出来ない 
AR2   #2       出来る 
AR2   #2 #8   出来る 
AR2   #3       出来ない 
php    なし     出来ない 
php    #2       出来る 
php    #2 #8   出来る 
php    #3       出来ない

説明は>>317の通り。
CL=CGI::Lite、Cp=CGI.pm、AR2=Apache2::Request、php=php(おまけ)。
#2 #8 は application/x-www-form-urlencoded; charset=UTF-8 のこと。
Apache2::Requestのつづり間違えてた。
0320nobodyさん2008/06/24(火) 10:11:34ID:???
cgiが正常ならクライアント側の問題だろ?
prototype.jsを遣わない理由がどこにある。
0321nobodyさん2008/06/24(火) 14:59:55ID:???
RequestHeaderが違ってくるのは、XMLHttpRequestメソッドとブラウザの問題だと思うんだけど。
ttp://www.fraction.jp/log/archives/2005/03/216

prototype.jsは関係ないんじゃない?と思ったが
XMLHttpRequestでgrepしてみると

/* Force "Connection: close" for older Mozilla browsers to work
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/

こんなのが。補正してるってことかな?


RequestHeaderによっては受け取れない部分はCGI::Liteの問題。
知らないとハマるから、良い検証だったと思います。乙
0322nobodyさん2008/06/25(水) 05:30:05ID:???
>>320さん >>321さん
318です。仰るとおり、送って来るReuestHeaderが異なるのは、各ブラウザ側の挙動の違いの問題です。

その後、教えて頂いたprototype.jsのXHR周りの動作について、手持ちのブラウザで基本的な動作確認をしましたが、
やはり送ってくるRequestHeaderはブラウザごとに違います。設定によりいくらかのヘッダの操作も出来ますが、
FireFox3で、当該の"chaesrt=..."の部分を消すことは出来ないようです。

( これもブラウザにより異なります。IEでもデフォで、"charset="が付いてきたりします。
 ここら辺の違いを吸収してくれるハズのライブラリで、ブラウザごとに分かち書きとかしないといけないのは、
 本末転倒のような気がします。まあJavascriptのことはスレ違いになるんで、言及はここら辺でやめときます。)
03233222008/06/25(水) 05:30:57ID:???
で、何が問題かと言うと、実は今自分の運営しているサイトで、CGI::Liteで書いた既存のcgiが動いてるんですが、
現在、日中平均で30req/s前後、ピーク時で90-100req/s程度のリクエストがあります。このスクリプトを導入した際に、
CGI.pmとCGI::Liteでそれぞれベンチを取ったのですが、本番環境と同一ハード,ソフトの環境で、
CGI.pmだと40rq/s位で限界、CGI::Liteだと150-160rq/s位までは持ちこたえられるとの結果を得ましたので、
CGI::Lite版を採用することに決めました。(その時は、最大50rq/s程度が想定でしたが・・・)

で、今回これと同じ処理をするcgiに、Jsからajaxリクエストを投げるような構成を考えていたのですが、
そのテストの段で、上記の>>311のような問題に行き当たったわけです。
現実問題として、速度や負荷の観点から、今回もCGI::Liteで行こうと思ったのですが、上記のような問題のため
(prototype.jsを使う使わないに関係なく)CGI::Liteが使えないので困ったなぁ とゆう感じです。
( 実は、mod_perl+Apache2::Requestでは、同様の処理で 1800rq/s! とかベンチ出たんですが、
 実験的な環境のため、そのまま本番環境には投入できません。)
0324nobodyさん2008/06/25(水) 10:26:42ID:???
>>323
当然考えているとは思うけど、CGI::Lite に手を入れてしまうのがリーズナブルなんじゃないかな。
parse_form_data() 内で、
$content_type eq 'application/x-www-form-urlencoded'
と判断しているので、これを =~ にでもすればいいだけなわけだし。
0325nobodyさん2008/06/25(水) 13:14:34ID:???
簡単なパースしかしないなら、モジュール使わない方法もあるんじゃね?
0326nobodyさん2008/06/28(土) 19:23:20ID:???
HTMLフォームから送信されてきた文字列の中からURLを探しだして
<a href=>のタグをくっつけたいんですが、cgiのURLとかで?が入ってると上手く置き換えできません。
これを回避する方法を教えていただければ幸いです。

$mojiretu =~ s/$url/<a href="$url">$url<\/a>/; #$ulに?が入ってると置き換えできない。
0327nobodyさん2008/06/28(土) 19:59:00ID:???
>>326
上手く行くかどうかしらんし、根本的な解決にはならんかも知れんが、
$mojiretu =~ s/\Q$url\E/<a href="$url">$url<\/a>/;
0328nobodyさん2008/06/28(土) 20:12:33ID:???
>>327
うはwできた
ありがとおお!!
0329nobodyさん2008/06/28(土) 22:15:55ID:???
「\E までのパターン指定メタ文字の意味を打ち消す」

ってどういう意味かな?
0330nobodyさん2008/06/28(土) 22:29:45ID:???
$str="a?b";

のとき、

/$str/

が

/a?b/

じゃなくて、

/a\?b/

に展開されるようにしてくれる。
0331nobodyさん2008/06/28(土) 22:33:22ID:???
?が「パターン指定メタ文字」なんだな、たぶん。

それで、?があると、そのあとに続く文字が
特別な意味をもつんだな。

だからそれをエスケープ?しなくてはならなくて、
そのための呪文という意味か。よくわかりました。
■ このスレッドは過去ログ倉庫に格納されています