【Perl】初心者コーナーPart11
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
02/03/27 12:53ID:wAXxxOxPいらっしゃーい、Perlの「コーディング」で困ってる人のスレです。
1:自分はこう言う事がしたい。
2:それでこんな風にやってみたが・・・
3:それだとこんなエラーが出て上手く行かなかった。
1と3が無いと誰も答えられないよ、良い回答は良い質問から。
一緒に勉強しましょう。
参考書籍はこちら【【Perl,CGI】参考書籍 第2版 】
http://pc.2ch.net/test/read.cgi/php/988809842/
CGIの質問はこちら【CGIだけどなんか質問ある Pert 5.01 】
http://pc.2ch.net/test/read.cgi/php/1015127347/l50
その他の雑多な話題は、【CGIに依存しないPerlの話題一般】
http://pc.2ch.net/test/read.cgi/php/991313362/
過去ログ、その他の役立ち情報は>>2-10を見よう。
0322nobodyさん
02/04/07 23:41ID:???0323やさしいお兄さん
02/04/07 23:49ID:???わたしが書いたほうが、約1.5倍速でした。318君は、目測でわたしが書いたほうが遅そうだと
書きましたが、どう見てもわたしが書いたほうがはやそうだったからベンチとってやったよ!
わたしが書いたほうは先頭からのマッチ部分までのみの取り出しなのに対し、303君のは先頭から
末尾までのパターンを確認する処理と括弧内にマッチした部分への置換というまわりくどい処理を
していることから考えて、どう見てもわたしが書いたほうが速いし、それに付け加えて複数OSにも
対応しているということだ。
Benchmark: timing 10000 iterations of 303, 316...
303: 0 wallclock secs ( 0.66 usr + 0.00 sys = 0.66 CPU)
316: 1 wallclock secs ( 0.38 usr + 0.00 sys = 0.38 CPU)
0324nobodyさん
02/04/07 23:49ID:???perlのスカラーはintじゃないという罠を踏まえたうえで、
とりあえず概算でいいなら、こんなんで。
$i = 1;
print $i*=10,"\n" while $i ne Inf;
0325(・∀・)イイ!
02/04/07 23:49ID:???とかく月曜日は閑散となりがちなので、明日も気合いを入れてがんがろう!
0326nobodyさん
02/04/08 01:20ID:6SHXOq5Lたまに
Benchmark: timing 10000 iterations of 303, 316...
303: 0 wallclock secs ( 0.66 usr + 0.00 sys = 0.66 CPU)
316: 1 wallclock secs ( 0.38 usr + 0.00 sys = 0.38 CPU)
って見るんだけど、これってどうやって取るの?
方法知りたいです。
0328nobodyさん
02/04/08 01:49ID:???あ、文字列の最後が改行じゃなかった場合にマッチしなかったのね。これでいいかな?
($str) = $str =~ /^((?:.*(?:\n|\z)){0,$limit})/;
Perl神の>>316氏にもプレゼント。
($str) = $str =~ /^((?:[^\x0D\x0A]*(?:\x0D\x0A|[\x0D\x0A]|\z)){0,$limit})/;
Benchmark: timing 100000 iterations of 316, ore...
316: 3 wallclock secs ( 3.96 usr + 0.00 sys = 3.96 CPU) @ 25278.06/s (n=100000)
ore: 2 wallclock secs ( 1.65 usr + 0.00 sys = 1.65 CPU) @ 60532.69/s (n=100000)
>326
ストップウォッチ
0329nobodyさん
02/04/08 01:50ID:???http://www.perldoc.com/perl5.6.1/lib/Benchmark.html
0330
02/04/08 15:23ID:cplvHQS4ありがとうございます。
もう正規表現わけわからんので正規表現だけの本購入しました。
PERLリファレンス系だと細かく書いてないので
正規表現奥が深いですね
0331nobodyさん
02/04/08 18:22ID:???人が書いた正規表現は、まさに「魔法の呪文」みたいなもんで、
使ってみれば確かに効果は出るんだけど、それがどういう理屈で
そうなるのか解読するのは骨が折れるんだよね。
0332nobodyさん
02/04/08 21:40ID:dY0mSfL0阪神は本来、神のチーム。
これくらいのゲームができて当たり前。
1938年に開幕7連勝した時に阪神は優勝した。
今年も9割方優勝する。
阪神電鉄の株価もウナギ昇りだ。
優勝すれば経済効果も核爆弾級だろう。
現在、阪神ファンの脳内モルヒネ分泌量は最高だ。
仕事にも遊びにもハリが出る。
阪神ファンが勝ち味に飢えていたが故に。
カーネル・サンダースは俺たち阪神ファンに17年間の試練を与えた。
今はそのことに感謝したい。
昼食時には是非ともKFCを利用したいと思っている。
0333nobodyさん
02/04/08 23:00ID:9Gr66QZ9表を細く平面的にしたいんですけど、
(こんな感じ→ttp://www2.pure.cc/~cle/yy-bbs/yybbs.cgi)
どこをどういじれば良いかさっぱりです。
誰かお願い。
0335nobodyさん
02/04/09 00:44ID:???Web製作板でスタイルシートのスレ探しに行け。
0338306
02/04/09 06:08ID:???すいません。えっと、
< < < > > < を < < < > > <
みたいに<>←→<>の相互変換をしたいのです。。
0339nobodyさん
02/04/09 06:49ID:N8wWg1s7@list = (A,B,C,D,E,F);
ってのがあって
EとFだけ取り出して別の配列に入れたい
場合ってのはどうやってやればいいんでしょうか
0340やさしいお兄さん
02/04/09 06:50ID:???これでどう?
%conv= ('<' => '<',
'>' => '>',
'<' => '<',
'>' => '>');
$_= '< < < > > <';
s/<|>|&(?:l|g)t;/$conv{$&}/g;
print;
0342やさしいお兄さん
02/04/09 06:58ID:???これでどう?
@list= qw(A B C D E F);
push(@new, splice(@list, $#list- 1, 2));
0343やさしいお兄さん
02/04/09 07:16ID:???やっぱりすなおに以下のようにしたほうが速いかな?
s/<|>|&[lg]t;/$conv{$&}/g;
0345nobodyさん
02/04/09 07:34ID:???$&は危険
s/([<>]|&[lg]t;)/$conv{$1}/g;
>342
負数のほうが簡潔
push @new, splice(@list, -2, 2);
0346やさしいお兄さん
02/04/09 07:37ID:???できるだけループ数を多くして3回とってみたらいずれも340のほうが速かったです。
つまり、[lg] よりも (?:l|g) のほうが速いという結果でした。
Benchmark: timing 100000 iterations of 340, 343...
340: 12 wallclock secs (11.21 usr + 0.00 sys = 11.21 CPU)
343: 12 wallclock secs (11.43 usr + 0.00 sys = 11.43 CPU)
0347nobodyさん
02/04/09 07:48ID:???まだ間に合うから、修行しなさい。
0349やさしいお兄さん
02/04/09 08:10ID:???でも以外でしょ?
0350nobodyさん
02/04/09 09:46ID:???@new = @list[ 4, 5 ];
0351nobodyさん
02/04/09 10:34ID:???0352nobodyさん
02/04/09 10:44ID:???Perlソースのテンプレートが欲しいのです。
ラマとラクダがまだ家に来てくれないので欲しいのです。
第一引数でフォルダを指定して、
そのフォルダ下にある全ファイルを読み込んで処理する
テンプレが欲しいのです。
ファイル処理をする関数名はdo_file
で、そこは私が作るんで。テンプレおねがいします。
0353☆
02/04/09 10:51ID:???そのバナーのカウントが1プラスされるようにしたいんですが、うまくいきません。
以下の構文でどこか間違っている個所があれば教えて頂きたいのですが、、
ちなみにQUERY_STRINGと$read_data[1]はリンク先URLです。
#バナーをクリックした時
if($ENV{'QUERY_STRING'} eq "$read_data[1]")
{
open (DATA,$datatext);
@data = undef;
@read_data =();
@data = <DATA>;
close DATA;
for($i = 0;$data[$i];$i++)
{
@read_data = split(/\t/,$data[$i]);
$read_data[4]++; #4列目はリンクカウント数
$lastdata[$i] = "$read_data[0]"."\t"."$read_data[1]"."\t"."$read_data[2]"."\n";
}
open(WRITE,">$datatext");
print WRITE "@lastdata";
close WRITE;
print "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;URL=$ENV{'QUERY_STRING'}\">\n";
exit;
}
0354nobodyさん
02/04/09 10:52ID:???キミは最初に質問と言っておきながら、いつの間にかクレクレ君に大変身ですか?
0355☆
02/04/09 10:56ID:???あ、すいません。構文間違えました
#4列目はリンクカウント数とかかれている部分、
$read_data[2]++;
で、2列目の間違いです。
0356352
02/04/09 11:07ID:???<>とか、きっとそういうのを使うとは思うんですが…
どうかおねがいします。教えてください。
ペコリm(_ _)m o0(いつのまにか…というより、もとよりそのつもりでしたが何か?
)
0357やさしいお兄さん
02/04/09 11:19ID:???これでどうでしょうか?動作確認はしておりませんが...
if ( $ENV{'QUERY_STRING'} eq $read_data[1] ){
open(DATA, $datatext);
while (<DATA>){
@read_data = split(/\t/);
$read_data[2]++;
push(@lastdata, join("\t", @read_data)."\n");
}
close DATA;
open(WRITE,">$datatext");
print WRITE @lastdata;
close WRITE;
print qq(<META HTTP-EQUIV="Refresh" CONTENT="0;URL=$ENV{'QUERY_STRING'}">\n);
exit;
}
0358nobodyさん
02/04/09 11:27ID:???最初に質問というのなら、具体的にどこの記述でいきづまっているのか、
具体的なコードを明示すべきだろ。
それもしないでおきながら調子のいいこと言って自分を正当化すんじゃねーよ!
0359☆
02/04/09 11:30ID:???どうもです。
でもそれで実行して再読み込みすると、データテキストに無限に数字が書き込まれてるんですが・・
それ以前の部分の処理が悪いんでしょうか?
0361nobodyさん
02/04/09 12:06ID:???>いらっしゃーい、Perlの「コーディング」で困ってる人のスレです。
>
>1:自分はこう言う事がしたい。
>2:それでこんな風にやってみたが・・・
>3:それだとこんなエラーが出て上手く行かなかった。
>
>1と3が無いと誰も答えられないよ、良い回答は良い質問から。
>一緒に勉強しましょう。
0362やさしいお兄さん
02/04/09 12:09ID:???そうですよね。処理の内容を考えずに書いてしまいました。チョット
データファイル内容がよくわからないのですが、リンク先URLはあらかじめ
データファイルに設定されているということならば以下のような感じかなと。
open(DATA, $datatext);
while (<DATA>){
chop;
@read_data= split("\t");
$read_data++ if $ENV{'QUERY_STRING'} eq $read_data[1];
push(@last_data, @read_data);
}
close(DATA);
open(WRITE,">$datatext");
for ( @last_data ){
print WRITE $_,"\n";
}
close WRITE;
print qq(<META HTTP-EQUIV="Refresh" CONTENT="0;URL=$ENV{'QUERY_STRING'}">\n);
exit;
0363やさしいお兄さん
02/04/09 12:20ID:???まちがってしまいました。ごめっ。
$read_data[2]++ if $ENV{'QUERY_STRING'} eq $read_data[1];
0364やさしいお兄さん
02/04/09 12:31ID:???またまちがってた。頭冷やしてきまーす。
push(@last_data, join("\t", @read_data));
0365☆
02/04/09 12:42ID:???ありがとうございます。
アクセス数の書き込みはうまく行きました。
でも今度はCGIにアクセスすると自動的に何度も何度もリロードされます。
0366やさしいお兄さん
02/04/09 12:54ID:???より速く処理をするために以下の書き方もアリだと思います。
常に以下のメタタグを返す処理ならば何度もリロードになるでしょう。
最終的にどうしたいの?
open(DATA, $datatext);
while (<DATA>){
@read_data= split("\t");
$ENV{'QUERY_STRING'} eq $read_data[1] ? ($read_data[2]++,push(@last_data, join("\t", @read_data)."\n")) : push(@last_data, $_);
}
close(DATA);
open(WRITE,">$datatext");
print WRITE @last_data;
close WRITE;
print qq(<META HTTP-EQUIV="Refresh" CONTENT="0;URL=$ENV{'QUERY_STRING'}">\n);
exit;
0368やさしいお兄さん
02/04/09 13:01ID:???$ENV{'QUERY_STRING'} にこのCGI自身がしていされていれば、
何度もこれを繰り返すの間違いでした。
0369☆
02/04/09 13:09ID:???<a href="banner.cgi?http://www.yahoo.co.jp/"><IMG SRC="banner.gif"></a>
のようになっていて、
バナーをクリックした時にこのサブルーチンが動くようにしたいんです。
すなわちbanner.cgiに直接アクセスした時には
バナー一覧だけが表示される、という形です。
0370nobodyさん
02/04/09 13:11ID:B5CaElBBmy @setting = <SET>
と書いたんですが、@settingには何も入ってないみたいなんです。
open (SET,"$PATH");
my @setting = <SET>
close (SET);
open (SET,">$PATH");
ならできるんですが、、、
0371やさしいお兄さん
02/04/09 13:12ID:???以下のようにして、メタタグをコメントにしてみては?
URL一覧かバナー画像かどちらか必要ないほうもコメントで。
while (<DATA>){
@read_data= split("\t");
print qq(<A href="$read_data[1]">$read_data[1]</A>\n); # URL一覧なら
print qq(<img src="$read_data[0]"><BR clear=all>\n); # バナー画像なら
$ENV{'QUERY_STRING'} eq $read_data[1] ? ($read_data[2]++,push(@last_data, join("\t", @read_data)."\n")) : push(@last_data, $_);
}
0372やさしいお兄さん
02/04/09 13:17ID:???@read_data= split("\t");の直後に以下を書くということかな?
print qq(<a href="banner.cgi?$read_data[1]"><IMG SRC="$read_data[0]" border=0></a><BR>\n);
0373☆
02/04/09 13:23ID:???いやいやいや、バナー表示のHTMLは別の所にあるんです。
このクリック数カウントの部分だけをsub countというサブルーチンで
呼び出したいんです。
クリック数を得るためリンクが「banner.cgi?〜」となっているんですが、
バナーをクリックするとbanner.cgiに飛んでしまう。
だからbanner.cgi?〜
↑ここの値、すなわち$ENV{'QUERY_STRING'}が存在する時、
このサブルーチン&count; を起動させたいわけです。
0374やさしいお兄さん
02/04/09 13:27ID:???+> だと、いきなりファイルが空になってしまいます。
open (SET,"+<$PATH");
my @setting= <SET>;
0375やさしいお兄さん
02/04/09 13:33ID:???なんとなくわかってきました。以前の処理を以下のブロックに入れるということかな?
勿論、メタタグは無しということで。スクリプトの最初のほうがいいかな。
if ( $ENV{'QUERY_STRING'}=~ /http:/ ){
exit;
}
0376nobodyさん
02/04/09 13:34ID:B5CaElBBどうもです。
読み込みはできましたが、書き込みが追加になってしまうのを上書きにしたいんですけど、
読み込み&上書きは一度にできないんでしょうか?
0377やさしいお兄さん
02/04/09 13:35ID:???チョットまずいかな、いかのようにしたほうがよかった
if ( $ENV{'QUERY_STRING'}=~ /^http:\/\// ){
exit;
}
0378やさしいお兄さん
02/04/09 13:37ID:???seek(SET, 0, 0); # これではじめのほうに巻き戻すナリ!
0379やさしいお兄さん
02/04/09 13:39ID:???truncate(SET, 0); # これも必要だね。
0380nobodyさん
02/04/09 13:42ID:B5CaElBBできました!
お付き合いどうもありがとうございました。
0381☆
02/04/09 13:44ID:???ありがとうございます!!
これでとりあえずバナーをクリックした時にURLにジャンプするようになりました。
しかしbanner.cgi自体をリロードすると、
datatextの中のデータとかバナーの数がどんどん増えていってしまいます。
0382やさしいお兄さん
02/04/09 13:58ID:???たしか、サブルーチンにして呼び出すということなので、
@last_data をさいしょのほうで初期化するのをわすれていました。
1どの処理でこのルーチンを複数回呼び出すとどんどん増えていきますね。
@last_data= ();
または
@last_data= -1;
または
@last_data= undef;
または
undef @last_data;
0383やさしいお兄さん
02/04/09 14:12ID:???うそを書いてしまいました。
@last_data= ();
または
$#last_data= -1;
または
undef @last_data;
0386邪魔
02/04/09 15:17ID:???自分で努力しろよ。
0387やさしいお兄さん
02/04/09 15:33ID:???うーん。いまひとつ全体がぼやけてしまったので。できればどこかにテキスト
ファイルとしてアップしてURLを書いてもらえれば、全体の動きがつかめやすい
のですが、そのCGIではバナーの表示やカウントアップ、そのほかどんな処理を
しているのか?? チョット混乱してきました。
0388306
02/04/09 15:34ID:???うまくできました。ありがとう御座いました。
0390nobodyさん
02/04/09 16:22ID:???0391
02/04/09 17:41ID:h5pnnRRdパッケージについてお聞きします
いままでサブルーチンしかつかったことがないのですが
パッケージのほうがよい処理がありましてパッケージにサブルーチンを移そうとしてるんです
でもそのまんまコピペだとうまく動いてくれません。
本とか見ても最初の宣言の仕方だけで
やってはいけないこととかでてなくて困っています。
特にお聞きしたいのはパッケージ中でjcode.plなどを呼び出していいのか
変数の定義をパッケージ内でしていいのか、ファイル読み込んでいいのかなどです。
もしかしてそういうことするためにパッケージってあるんじゃないのかもしれませんが
教えてください。
本には
package PacTest ;
use Exporter ;
@P_TEST::ISA = ('Exporter');
@P_TEST::EXPORT = ('subtest');
sub subtest(){}
1;
ここまでしかでてなくて・・・
0392nobodyさん
02/04/09 18:01ID:???ok
>変数の定義をパッケージ内でしていいのか
ok
>ファイル読み込んでいいのか
ok
他に何か。
0393
02/04/09 18:10ID:h5pnnRRdありがとうございます。
う〜む、そしたらなぜコピペで動いてくれないんだろう・・・
パッケージを使うときのタブーみたいなものありますか?
0394nobodyさん
02/04/09 18:18ID:???@ISA = ('Exporter');
@EXPORT = ('subtest');
0395
02/04/09 19:17ID:h5pnnRRdここに書くためにかきなおしたんですがそのまちがいです
0396nobodyさん
02/04/09 19:54ID:???タブーがないのがPerlって気もするが…
「コピペで動いてくれない」ってコピペしたコードがuse PacTest;でエラーが出るって事か?
ところで話はずれるが@ISAとかにパッケージ名書くより
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(subtest);
の方が一般的な気がする。ourとuse baseでもいいけど。
0397
02/04/09 20:00ID:h5pnnRRd本にでてたやり方なんですけどね
秀和だめですね
0398396
02/04/09 21:03ID:???それより俺が聞きたいのはどうやったらエラーが出たのかという状況説明なんだが
0399
02/04/09 21:31ID:h5pnnRRdウェブマスターに聞けエラーです
0400nobodyさん
02/04/09 21:45ID:???0402
02/04/09 22:42ID:h5pnnRRd技術評論社は(゚∀゚)イイ
ソフトバンクは(´・ω・`)ショボーン
0403貴様ら教えて下さい
02/04/09 22:45ID:sR6b9WNM最終的には数万人規模のものにするらしいんです。(無理くせーけど。
普通にsendmailで送るのは無理っぽいですし、
どうしていいものかサッパリわかりません。
皆様ならどうやるでしょう?
0405nobodyさん
02/04/09 23:56ID:???0406貴様ら教えて下さい
02/04/10 00:47ID:RNZ++qE3あ、それともBccで数万件指定するのか?
いけるのか?
どうなのか?
>>405
お、使えるかも。
ちょっと見てみる。
0407nobodyさん
02/04/10 00:54ID:???0408nobodyさん
02/04/11 02:06ID:8LiumuzI単純にファイルから数字を読んで、1足して書き込むようなプログラム
(アクセスカウンタみたいな感じ)を作りたいのですがうまくいきません。
どうやら読み書き両用オープンがうまくいってないみたいなんです。
open(FILE,"+> data.txt");
$x=<FILE>;
print $x;
exit;
試しに上のようにすると、なぜか何も標準出力に出力されません。
open(FILE,"data.txt");
$x=<FILE>;
print $x;
exit;
これだと、ちゃんとファイルの中身が標準出力に出力されます。
どうしてなんでしょう?
環境は WINDOWS XP + Active Perl です。
よろしくお願いしますm(_ _)m
0410nobodyさん
02/04/11 02:49ID:???この前もまったく同じ質問があったが、過去レスとか見てる?
+> だといきなりファイルが空になるゾ!
+< で読み込んで
seek(FILE, 0, 0); で巻き戻して
truncate(FILE, 0); でファイルを空にした上で書きこむ
0412nobodyさん
02/04/11 08:32ID:8LiumuzI本などで「+>」は「読み書き両用オープン」って説明されていますが
実際には「書き」しかできないってことですか?(オープンした瞬間データ消えるから)
0414nobodyさん
02/04/11 11:06ID:QakPtgEu0415nobodyさん
02/04/11 12:56ID:???実際には「書き」しかできないってことですか?
これ前から気になってた。
413の答えで納得した。
でも「書いた直後に読みたい」なんて思った事ないな、、
0417nobodyさん
02/04/12 01:00ID:???使用したいのですが、STDIN が思うように動きません。
STDOUT は >>171, >>181, >>184 を参考にしてできたのですが、
<> を使う時はルールが違うのですかね。
わかる方教えて頂けませんでしょうか?
#!/usr/local/bin/perl -w
my %hash = ( in => \*STDIN, out => \*STDOUT );
while (< {$hash{in}} >) { # <= ココが STDIN の置き換えにならない
print {$hash{out}} $_;
}
exit 1;
出力結果は GLOB(0x8103460) のみです。
0418nobodyさん
02/04/12 02:10ID:???グローバルなものをなぜハッシュに入れるのかは敢えて聞かないとして・・・
$tmp = $hash{in};
<$tmp>
とスカラーに格納すれば大丈夫みたい。
ハッシュや配列の形ではだめだった。
$tmpは間接ファイルハンドルと解釈するが、$hash{in}はファイル名グロブに
解釈される仕様のようです。試しに次のような使い方は正常に機能した。
$t{a} = "*.txt";
@txt = <$t{a}>;
ということで、スカラー変数を使いましょう。
0419417
02/04/12 02:54ID:???わざわざ試して頂いて有難う御座います。
実はサブルーチンへ値を渡すのにハッシュを使っていたのですよ。
個人的に STDIN と STDOUT は同じルールで使って行きたい
ですので、実際にはこういう感じで使いましょうかねぇ。
#!/usr/local/bin/perl -w
package main;
exit &main;
sub main {
$ARGV[0] && open(STDIN, $ARGV[0]);
$ARGV[1] && open(STDOUT, "> $ARGV[1]");
return &func(in=>\*STDIN, out=>\*STDOUT);
}
sub func {
my %init = (in => \*STDIN, out => \*STDOUT, @_);
my ($in, $out) = ($init{in}, $init{out}); # <= ●
while (<$in>) { print $out $_; }
return 1;
}
貰った値の正当性を、関数側でチェックしてから使うルールなら
そんなに無駄な処理でもない・・・あ、でも結局ファイルハンドルか。
0420nobodyさん
02/04/12 03:07ID:???■ このスレッドは過去ログ倉庫に格納されています