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

【Perl 】初心者コーナーPart6

■ このスレッドは過去ログ倉庫に格納されています
0001undefさん2001/07/26(木) 00:40ID:???
初めて来た方、初心者はまずこのスレッドから始めよう。
尋ねる前に同じ質問がないかこのスレや旧スレ、及び>>2のリンクを一通り見てみよう。
案外答えはもう書かれているかもしれない。
02017292001/08/06(月) 23:51ID:Mx2WAaZU
Perlの書き方について質問させて。
「メモリの浪費」を抑えたいんだけど、いったい具体的にどういうことを
すればいい?そもそも「無駄に食う」ってのはどういう書き方をしたものなの?
初心者でスマソ。
02021532001/08/07(火) 00:00ID:???
はわわ・・gzip・・頑張ります・・。
0203名無しさん@お腹いっぱい。2001/08/07(火) 01:27ID:???
>>201
悪: @lines = <IN>;foreach (@lines){ ... }
良: while(<IN>){ ... }
0204名無しさん@お腹いっぱい。2001/08/07(火) 01:48ID:bTCo0M5g
>>203で、<IN>のx行目を操作したいとき、@linesにセットしないで
なんとかすることは可能でしょうか?
0205名無しさん@お腹いっぱい。2001/08/07(火) 02:01ID:???
>>204
可能です
0206名無しさん@お腹いっぱい。2001/08/07(火) 02:06ID:bTCo0M5g
>>205
そうなんですか。。。
今まで、とりあえず配列にセットして、popやらspliceやらの関数使ってました。
勉強しに逝ってきます。
02077292001/08/07(火) 08:58ID:swpPnFjU
>>203
すっきり書けるものを、余計なプロセスを経てるということ?
他にはないっすかねぇ。気持ち的にforeach〜よりもuntilとかの
制御を使うほうが重い気がするんだけど、どう?
0208名無しさん@お腹いっぱい。2001/08/07(火) 09:08ID:???
ちょっと質問したいんですが、

てきとー
<!--a-->
てきと

あああ
<!--b-->

と言う文があったとして<!--a-->と<!--b-->とその間の文を消したいんだけどどうすればいい?
s/<!--a-->.*<!--b-->//;だとできなかったんだけど。
0209名無しさん@お腹いっぱい。2001/08/07(火) 09:21ID:???
>>729
根本的に違う気がする。
@line = <IN> ってのは全てに配列に読むことによって、メモリを非常に使う。
それに対してwhile (<IN>) {} は一行づつ読み込むことによって、
メモリの消費が大きくならない。スピードは殺しているだろうが。

>>208
s修飾子をつけて単一行として処理。
s/<!--a-->.*<!--b-->//s;
0210名無しさん@お腹いっぱい。 2001/08/07(火) 12:17ID:???
場違いとは思いますが、あえて聞かせてください。
ton.2ch.net/test/read.cgi?bbs=sec&key=996966367&st=40&to=40&nofirst=true
これがperlプログラムのコーディング上のチェックミスらしいんですが
本当のperlhackerさんに掛かれば掲示板のタグチェックなんて意味を
なさないと言う事でしょうか?

どうしても興味が有ったので可能性と言う事で、お聞きしました。
方法を知りたいのでは無いんです。
場を乱したらごめんなさい。放置してくださいませ。
0211名無しさん@お腹いっぱい。2001/08/07(火) 12:17ID:???
メモリ消費==変数の数 と考えればわかりやすいんでは?
配列だってa[0]で一つの変数分のメモリを消費します、これが100個
あれば変数100個分のメモリを消費します。

処理速度!=メモリ消費 です、メモリ消費を抑えるために例えば
配列に入れるんではなく1行づつファイルに書き出したりしてたら
速度は遅くなります。

当たり前のことを長々と書いてしまって恥ずかしい。。。
0212名無しさん@お腹いっぱい。2001/08/07(火) 12:56ID:???
配列が滅茶苦茶大きくなれば1行づつの方が早くなるけどな。
# そこまで大きいデータをTEXTで保存はせんだろうが
0213名無しさん@お腹いっぱい。2001/08/07(火) 13:07ID:t8arwgAY
case sensitiveのサーチエンジンのスクリプトを
case insensitiveにしたいのですが
良い記述方法等ありますでしょうか?
0214名無しさん@お腹いっぱい。2001/08/07(火) 13:12ID:???
>>210
フィーネはcgiの問題とは言ってるがbbs.cgiの問題とは言っていないところ
がポイント
0215名無しさん@お腹いっぱい。2001/08/07(火) 14:12ID:???
>>210
ドキュソの俺にはどうやってるのかサッパリ分からん…。
しかもCGIのバグって…?
0216名無しさん@お腹いっぱい。2001/08/07(火) 14:24ID:???
フィーネが前言ってたとおりログに直接書いてんだよ。
CGIのバグを利用して「書き込んでる」とは言っていない点にも注目。
02177292001/08/07(火) 15:25ID:m8P3Xhl6
ありがとう、みんなレベル高いな・・・。
「処理速度!=メモリ消費」は目から鱗だったよ。
「箱庭」「FFなんたら」が敬遠されてるけど、サーバ側は何が不満なの?
どこかのサーバでは“メモリ消費が激しいCGI”と説明してたけど、
サーバにとって問題のあるCGIってのは「メモリ消費>速度」なのかな。
0218名無しさん@お腹いっぱい。2001/08/07(火) 15:48ID:???
リロードの回数がチャットの比じゃないとか? よく知らないけど。
0219名無しさん@お腹いっぱい。2001/08/07(火) 15:52ID:???
メモリの話なので便乗質問です。

なるべくメモリ消費を少なくする為にundefで変数を初期化するのは
良い事なのでしょうか?
undefが入る分、処理は遅くなると思います。
よっぽどメモリを喰うようなスクリプトでなければ気にする必要は
ないのでしょうか?

いつも悩んでるんです・・・。
02202152001/08/07(火) 17:43ID:???
>>216
ナルフォドそれなら納得。サンクス
0221名無しさん@お腹いっぱい。2001/08/07(火) 17:45ID:???
undefしてもメモリが開放されるとは限らん…よな、確か。
0222名無しさん@お腹いっぱい。2001/08/07(火) 18:22ID:???
>>221
まじで?じゃあundefの存在意義は?
ソースが分かったら教えてちょうだい。
02232222001/08/07(火) 18:31ID:???
よく考えたらメモリ開放する意味以外でもundef使ってるや。
存在意義はあるね。
けどソースが分かったら教えてちょうだい。
02242212001/08/07(火) 19:41ID:???
たしかプログラミングPerlで見た気がするが…よく覚えておらん。スマソ
Perlのソース見れば分かるんだろうが…(;´Д`)
0225名無しさん@お腹いっぱい。2001/08/07(火) 20:32ID:???
メモリの開放ってどうやるんだい?
そして同じ名前の変数を何度も使いまわせば浪費にならないのかい?
0226名無しさん@お腹いっぱい。2001/08/07(火) 20:34ID:???
メモリの解放まで気にするならPerlを使ってはいけませんとか
0227名無しさん@お腹いっぱい。2001/08/07(火) 20:41ID:???
詳しい人出て来て教えて欲しいage
0228名無しさん@お腹いっぱい。2001/08/07(火) 20:48ID:???
数百KB程度のことなら>>226の言うことが正しいのかもしれぬ。
ハッシュ一要素につき1KBくらい消費するとか聞いたことあるし。
0229名無しさん@お腹いっぱい。2001/08/07(火) 21:44ID:???
undefしたオブジェクトに関連する領域はすべて回収して再利用される。
しかし殆どのバージョンのUNIXでは、領域をシステムに返却されない。

青らくだにあるな。

>>219
結局、メモリリークをおさえるか、処理速度を優先させるか。
これはケースバイケースだったりするわけで。
どちらか問われない、又は問題無い状況であれば、好みで使えばいいかと。
0230名無しさん@お腹いっぱい。2001/08/07(火) 22:34ID:???
$var = "ABC";
コレってメモリをいくらぐらい食いますか?
0231名無しさん@お腹いっぱい。2001/08/07(火) 23:21ID:???
>>230
気になるのならどうにかして試して調べろ。
0232名無しさん@お腹いっぱい。2001/08/07(火) 23:30ID:???
>>231
出来ないくせに大きな口叩くなよ(大爆笑)
0233名無しさん@お腹いっぱい。2001/08/07(火) 23:39ID:???
やっぱり青らくだは一冊買っておくべきかな?初心者は。
箱庭風ゲームを作るつもりだが、メモリ消費と処理速度、どっちを
優先した方が良いと思う?箱庭みたいにご指名で「使用不可」
されたくはないからな…。
02342312001/08/07(火) 23:43ID:???
1KB程度。
OK?>>232
0235 2001/08/07(火) 23:45ID:iLCparaY
せめてPerlも整数型、文字列型、オブジェクト型くらいには分けるべきだ
0236Crow2001/08/07(火) 23:47ID:???
print <<test;

#この中でサブルーチンを直接読み込んだり、
#計算したりする事出来る?

$kotae=$tmp*$check;#こんな感じで

test
0237名無しさん@お腹いっぱい。2001/08/07(火) 23:51ID:???
>>236
自分で試せよ。
0238名無しさん@お腹いっぱい。2001/08/07(火) 23:56ID:???
>>236
print <<test;

test

$kotae=$tmp*$check;#こんな感じで

print <<test

test
0239名無しさん@お腹いっぱい。2001/08/08(水) 00:04ID:???
print <<test;

${ \do{ $katae = $tmp * $check; } }

test
0240名無しさん@お腹いっぱい。2001/08/08(水) 01:17ID:rNhUL.Uw
print <<test;

@{[ $katae=$tmp*$check;]}

test
0241名無しさん@お腹いっぱい。2001/08/08(水) 06:02ID:???
メモリか…

 $hogege = 1024kb_str;#1Mぶんくらいの文字列
 hoge;

sub hoge{
 my $hoge = $hogege;

 $hoge = s/sage//g;
 $hoge = s/age//g;
 $hoge = s/hage//g;
 $hoge = s/uge//g;

 $hogege = $hoge;

 $hoge = 0;
}

最後に0でクリアするのって意味あるのだろうか…
0242名無しさん@お腹いっぱい。2001/08/08(水) 08:52ID:???
>>241
無い。
プライベート変数はスコープ抜けると自動的に破棄されます。
というか、プライベート変数にコピーする理由も無いような。
0243名無しさん@お腹いっぱい。2001/08/08(水) 13:01ID:79X/nc36
CGIで日本語ドメインを検索できるようにしたいんだけど、
PerlでSJISをUNICODEに変換するには、どのように記述すれば良いのですか?
0244名無しさん@お腹いっぱい。2001/08/08(水) 13:42ID:???
>>243
モジュール使いましょう。
検索すればいくらでも出てくるかと。
02452432001/08/08(水) 14:54ID:2OjC6AHM
モジュールって jcode.pl みたいなやつですよね?
0246名無しさん@お腹いっぱい。2001/08/08(水) 15:05ID:???
#!/usr/local/bin/perl

use strict;

print "Content-type: text/html; charset=EUC-JP\n\n";
print <<"EOM";
テキストを出力
EOM

exit;

use strict; を宣言すると上のようなスクリプトが動かなくなります。
こう言う場合は宣言してはならないものなのでしょうか。
0247名無しさん@お腹いっぱい。2001/08/08(水) 15:20ID:???
>>246
動くが?
0248名無しさん@お腹いっぱい。2001/08/08(水) 15:25ID:???
時々居るんだよな、
コーディングミスをuse strictの所為にする厨房が。
0249名無しさん@お腹いっぱい。2001/08/08(水) 15:27ID:???
>>246
動きますが?
0250名無しさん@お腹いっぱい。2001/08/08(水) 15:30ID:???
やはり動きますよねぇ…なんで動かないのだろう。
ちなみにテキストの内容に $ とか @ とかは入って無いです。

んー…
0251名無しさん@お腹いっぱい。2001/08/08(水) 15:35ID:???
エラーメッセージよめや。
0252名無しさん@お腹いっぱい。2001/08/08(水) 15:41ID:???
ニフティはエラーメッセージ出ないので分かりません。
というかローカルでは動くんですが…
0253名無しさん@お腹いっぱい。2001/08/08(水) 15:41ID:???
動くね、うーん結構深かったりして  違うか
多分これからもエラー出まくるから出来ればコマンドラインでwcした方が
良いよ。cgiでやるならKcache入れるとか。
探せばごろごろ出てくる。
0254名無しさん@お腹いっぱい。2001/08/08(水) 15:53ID:???
>>252
サーバで実験すんな。ローカルでやれや。
0255名無しさん@お腹いっぱい。2001/08/08(水) 15:55ID:???
>>246
2chには無理。
0256名無しさん@お腹いっぱい。2001/08/08(水) 16:06ID:???
>>243
jcode.plはライブラリだ。
0257名無しさん@お腹いっぱい。2001/08/08(水) 16:07ID:???
>>254
ローカルでは動いてると書いてるようだが。
0258名無しさん@お腹いっぱい。2001/08/08(水) 16:09ID:???
>>252
shebang行が違うというのは無しの方向で。
0259名無しさん@お腹いっぱい。2001/08/08(水) 16:14ID:???
>>258
ウチもニフだが合ってる。
ってかマジで動かないねぇ。
サーバのせいにして終わりにしておけ。
0260名無しさん@お腹いっぱい。2001/08/08(水) 16:15ID:???
niftyは@INCにパスが通って無いんじゃない?
0261名無しさん@お腹いっぱい。2001/08/08(水) 16:18ID:???
perlのバージョンを調べてみるとか。
strict.pmが無いならアウト。
0262名無しさん@お腹いっぱい。2001/08/08(水) 16:26ID:???
http://homepage.nifty.com/cgi/
かな?
0263名無しさん@お腹いっぱい。2001/08/08(水) 16:28ID:???
明記されてるな。

perlのバージョンは5です。 (ただし、perl5での標準的なモジュールは使用できません)

ということで、strict.pmすら無いというオチかと。
0264名無しさん@お腹いっぱい。2001/08/08(水) 16:43ID:???
相当なボンクラだけどかなり口は立つと見た。
いいな ベシャリ出来るって  いや ある意味不幸か ヽ(´ー`)ノ
02652642001/08/08(水) 16:45ID:???
間違えた、ゴメンネ>>皆さん
許して  30時間寝てないの。。。。。。
0266名無しさん@お腹いっぱい。2001/08/08(水) 16:50ID:???
>>264
今一番勢いの良いスレに書こうとしたと見たが(w
0267名無しさん@お腹いっぱい。2001/08/08(水) 17:00ID:???
ニフはモジュール用意してないんですね…

分かりました、みなさんレスどうもでした。
0268名無しさん@お腹いっぱい。2001/08/08(水) 17:29ID:???
ニフにモジュールが無いってのは結構有名な話だと思ったが…
0269名無しさん@お腹いっぱい。 2001/08/08(水) 20:23ID:???
知らなかったよ、標準モジュールも無いってちょっとヒドイね
0270名無しさん@お腹いっぱい。2001/08/08(水) 20:37ID:???
お前ら、いつまでsageてるんだよ
0271名無しさん@お腹いっぱい2001/08/08(水) 21:22ID:???
すみません、xxx.datのなかにある内容を消すにはどうしたらいいんですか?
xxx.datの中身が

127.0.0.1
127.0.0.1
127.0.0.1
127.0.0.1

だとしたら、これを消したいんです。
0272名無しさん@お腹いっぱい。2001/08/08(水) 21:24ID:???
open FILE, ">xxxx.dat";
close FILE;
もっとスマートな方法ありそうだけど。
02732722001/08/08(水) 21:26ID:???
xが1つ多かった。逝ってくる。
02742712001/08/08(水) 21:32ID:???
ま、まだ逝かないでくださいよっ。
その線で、datに何かを書き込む形で消すことはできませんか?
02752712001/08/08(水) 21:35ID:???
open( FILE , "+<xxx.dat" );
while( <FILE> ){ push ( @IP , $_ )};
#ここでなにかやって
print FILE @IP;
close FILE;
って感じに。
0276名無しさん@お腹いっぱい。2001/08/08(水) 21:35ID:???
print FILE "nanika\n";
とほほとか見ると結構わかるよ
0277名無しさん@お腹いっぱい。2001/08/08(水) 21:37ID:???
ん? それで良いじゃん??
02782712001/08/08(水) 21:48ID:???
いえ、これだと@IPにxxx.datのIPが入っているからそのまま書き込んじゃいます。
で、途中で@IPをどうにかしてから書き込みして消したいんです。
0279名無しさん@お腹いっぱい。2001/08/08(水) 21:53ID:???
>>271=>>275
open( FILE , "+<xxx.dat" );
while( <FILE> ){ if($_ ne "127.0.0.1\n";){push ( @IP , $_ )}};
print FILE @IP;
close FILE;

こんな感じ?
02802712001/08/08(水) 21:54ID:???
全部の配列
foreach $IP (@IP){ $IP = ();}
ってやっても消えないんですよね…。
foreach $IP (@IP){ $IP = "\n";}
も4行だけもとIPが改行されるだけで消えるわけじゃないし。
0281名無しさん@お腹いっぱい。2001/08/08(水) 21:55ID:???
どうしたいのか全然わからねぇ。例えばでいいから
>>271の状態から何をどういう状態に持っていきたいのか
具体的に書いてみ。
02822712001/08/08(水) 22:04ID:???
>>281
すみません。
xxx.datに他人のいろいろなIPを「1日だけ」保存しておきたいんです。
これは1日に1度しかCGIを利用できないようにするためです。
で翌日、保存しておいたIPを全て除去したいんです。
02832712001/08/08(水) 22:09ID:???
具体的に書くと、
( $sec , $min , $hour , $day , $mon , $year ) = localtime( time );

open( FILE , "+<xxx.dat" );
while( <FILE> ){ if($_ ne "127.0.0.1\n";){push ( @IP , $_ )}};

#$IP[0]に日付が書いてある。
#$dayと同じ日ならIPを後ろに追加して、
#$dayと違う日ならxxx.datの中身は$IP[0]=$day;だけにしたい。

print FILE @IP;
close FILE;
0284名無しさん@お腹いっぱい。2001/08/08(水) 22:09ID:???
んで、>>272じゃダメなの?
ファイルごと消したいなら、
unlink('xxx.dat');
だし。
>>274はどういうことよ?
0285名無しさん@お腹いっぱい。2001/08/08(水) 22:09ID:???
>>282
一日一度(23:59と0:00はOK)か、24時間おきかにもよらない?
細かいことだけど。
02862852001/08/08(水) 22:11ID:???
先に書かれたか。
一つの手段として、xxx.datを${day}.datにしてしまう手もある。
そして、古いログを自動削除するように書き加える。
02872712001/08/08(水) 22:15ID:???
>>286
そういう手もあるんですか。

open FILE, ">xxxx.dat";
↑これはdatの中身をいったん消去するんですか?
0288名無しさん@お腹いっぱい。2001/08/08(水) 22:18ID:???
>>287
一旦消去するよ。
てかそれくらいは試せばわかるだろ。
02892842001/08/08(水) 22:22ID:???
あ、かぶった。
なるほど。

$IP = 新しいIPアドレス
として、
open( FILE , "+<xxx.dat" );
$oldday = <FILE>
if ($day eq $oldday) {
  seek(FILE, 0, 2);
  print "$IP\n";
} else {
  seek(FILE, 0, 0);
  trucate(FILE, 0);
  print "$DATE\n";
}

close FILE;

じゃだめ?
02902712001/08/08(水) 22:40ID:???
かっこ良すぎです>>289,>>285.
おかげで無事難問を突破できました。もうどっちの方法でログを消そうか迷ってます。
truncateがスマートで美しいだけど、${day}.datもファイル生成あたりが上級者っぽいし。

#これでまたKENT氏に1歩近づいた…。
0291三下2001/08/08(水) 23:32ID:???
先生、ちょっとイイですか!?
変数を$_このていどに省略する理由ってのは
見た目だけですかい!?
0292名無しさん@お腹いっぱい。2001/08/08(水) 23:51ID:???
>>252

use strict くらいの効果なら,直接コードに書いてしまったら?
strict.pm を見れば一目瞭然だけど一応.

BEGIN { $| = 0x00000002|0x00000200|0x00000400 } # 左からrefs,subs,vars


%INC を見ればそのスクリプトがどのファイルを使っているか分かるから,
これを使って,Nifty 用スクリプト(モジュールを全て展開する)を生成する
トランスレータを作るという手もあるかも.
0293名無しさん@お腹いっぱい。2001/08/08(水) 23:54ID:???
一緒にstrict.pm(とその他いくつか)をあぷするという手もある
0294名無しさん@お腹いっぱい。2001/08/09(木) 00:03ID:???
>>292
$|じゃなくて$^Hな

わざわざ展開トランスレータを書くくらいなら
アプしたほうがいろんな意味でいいと思うがね。
0295名無しさん@お腹いっぱい。2001/08/09(木) 00:03ID:???
ローカルでuse strict;環境で動くって確認されたなら、
その行を削ってアップすりゃいいじゃん。
0296名無しさん@お腹いっぱい。2001/08/09(木) 02:08ID:1PgCYU2A
上のほうで出てるのとは状況が違うんですが、ローカルで動いてたスクリプトが
サーバー上で動かない理由って何がありますかね?

Winで作っててサーバーはUNIXです。スクリプトはEUCで保存して、改行はLFにしました。
別のファイルをrequireしてますが、それはSJISです。

どうか教えてください。
0297名無しさん@お腹いっぱい。2001/08/09(木) 02:12ID:???
>>296
1:user/bin/perlの違い
2:絶対パスと相対パスの違い
3:Perlのバージョンの違い
4:使用できるモジュールの違い
5:パーミッションの違い

続きよろ。>>298
0298名無しさん@お腹いっぱい。2001/08/09(木) 02:21ID:1PgCYU2A
>>297
レスありがとうございます。
言われた点をチェックしてみます。
また後できます。
0299名無しさん@お腹いっぱい。2001/08/09(木) 02:31ID:???
モジュールの話が出ているので便乗して質問です。
ウチもニフティなんですが、
モジュールを使うときはインストールしなければならないと聞いたことがあります。
インストールには特別な作業が必要なんでしょうか。
それとも、ただアップして requier か何かで呼び出せば良いんでしょうか。
0300名無しさん@お腹いっぱい。2001/08/09(木) 02:44ID:1PgCYU2A
>>297
言われた点をチェックしてみました。

1: Perlのパスはあってます。
2: それはrequireするファイルのパスの事でしょうか?もともと相対パスで書いてあり、合っています。
3: Perlのバージョンは5です。特に問題ないはずです。
4: モジュールは使用していません。
5: パーミッションは755です。これで他のスクリプトは動いています。

この状態で考えられるほかの原因の心当たりがありましたら教えてください。
よろしくお願いします。お手数かけます。
0301名無しさん@お腹いっぱい。2001/08/09(木) 02:45ID:???
perlのバージョンは5でも、細かい違いによって(以下略
みたいな事は無いかな?
■ このスレッドは過去ログ倉庫に格納されています