トップページphp
1001コメント294KB

Perl コーディング初心者質問コーナー Part26

■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん03/07/24 19:48ID:???
いらっしゃーい、Perlのコーディングで困ってる人のスレです。

【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。

1: 自分はこう言う事がしたい。
2: それでこんな風にやってみたが・・・
3: こんなエラーが出て上手く行かなかった。

最低でも1と3が無いと誰も答えられないよ。
ソース貼る時は、全角スペースでインデント忘れずに。
良い回答は良い質問から。一緒に勉強しましょう。

関連スレ
【Perl上級者コーナーPart01】
http://pc2.2ch.net/test/read.cgi/php/1024741312/
CGI: Common Gateway Interface part 11
http://pc2.2ch.net/test/read.cgi/php/1055597189/
【Perl,CGI】参考書籍 第三版
http://pc2.2ch.net/test/read.cgi/php/1030209573/
【 スクリプト改造工房 PART 6 】
http://pc2.2ch.net/test/read.cgi/php/1047806915/

過去ログやお勧めサイトは >>2-10
0133nobodyさん03/07/27 11:47ID:???
ループのたびにsplitされたら、永久にまわり続けるだろう。
013413203/07/27 11:54ID:???
…そうか。少しは考えろよ俺。
くだらない質問失礼しました。
0135あぼーんNGNG
あぼーん
0136あぼーんNGNG
あぼーん
0137nobodyさん03/07/27 14:00ID:???
>>132
なんで最近こんな奴ばっかなんだよ。
>splitは1回だけ実行されるのでしょうか。
他人に聞くよりPerlに聞いた方が正確だし早い。やればわかるだろ。
0138nobodyさん03/07/27 17:20ID:LVhmum4F
テキストから、条件にあてはまるものの件数、文字、を出力します。
件数を先に出力したいから、
$n=0;
open(DATA,"data.txt");
foreach(<DATA>){
if($_ =~ m/$keyword/){ $n+=1; }
}

print "$n件見つかりました。<br><br>";
close(DATA);
open(DATA,"data.txt");

foreach(<DATA>){
if($_ =~ m/$keyword/){ print "$_<br>"; }
}

こうやってるんですが、2回データ開くってのが、ソースが変だし、効率が悪いと思うんですが、効率いい方法ありませんか?
「件数」を先に出力するので、この方法以外考えられません。
条件に当てはまったものを、配列に入れて、後で出力ってのも考えましたが、
配列は効率わるそうで・・・
ご教授お願いします
0139nobodyさん03/07/27 17:22ID:???
無限ループが心配な場合は$f++>=100 last;
とかストッパーかけておくと良い。
0140nobodyさん03/07/27 17:25ID:???
while (??) {
if ( 表示する条件 ) { continue; }
$n++;
if (??) { contine; }
if(??) { contine; }
print $_; or $xx = $_;
}

$n件見つかりました
結果$xx
0141nobodyさん03/07/27 17:27ID:???
if (??) { contine; }
if(??) { contine; }
↑ゴメン s/contine/last/g
ついでに、ここは表示するページのはじめの数から後の行数を先に求めておく。
0142nobodyさん03/07/27 17:45ID:LVhmum4F
>>140
ゴメン。難しくて理解できない・・・
ちょっと解説お願いできますか?
0143nobodyさん03/07/27 17:54ID:???
配列は効率が悪いの?
0144nobodyさん03/07/27 17:59ID:???
同じファイルを2回読むよりは効率いいんでない?
メモリは食うだろうが。
0145nobodyさん03/07/27 18:09ID:???
$n=0;
open(DATA,"data.txt");
while(<DATA>){
if($_ =~ m/$keyword/){ $n+=1; $str .= "$_<br>"; }
}
close(DATA);
print "$n件見つかりました。<br><br>$str";


これじゃだめなのん?
オープン2回が気になるなら、seekで戻せば開きなおす必要はなし。
0146nobodyさん03/07/27 18:15ID:???
@hit = ();
$n=0;
open(DATA,"data.txt");
while(<DATA>){
if(/$keyword/o){
push(@hit, $_);
$n++;
}
}

print $n. '件見つかりました。<br><br>';

foreach(@hit){
print $_. '<br>';
}
close(DATA);

んじゃ、配列使うやつ。
DATAファイルハンドルは避けたほうがいいよ。
改行もしっかり処理しよー。
0147nobodyさん03/07/27 19:03ID:bAtOJVka
Aというサーバーで動くperlスクリプトが
Bというサーバーでは動きません。
原因として考えられるのって何があるでしょうか?
0148nobodyさん03/07/27 19:04ID:???
>>147
スレ違い
0149nobodyさん03/07/27 19:25ID:???
http://pc2.2ch.net/test/read.cgi/php/1056078605/820
0150nobodyさん03/07/27 19:58ID:LVhmum4F
>>143
効率は悪くないんですかね・

>>145>>146
ありがとうございます。
ソートもできたらなぁ、と今思っていたので配列にすることにします。

どうもありがとうございました
0151あぼーんNGNG
あぼーん
0152あぼーんNGNG
あぼーん
0153nobodyさん03/07/27 20:59ID:???
配列につっこんでまた回すよりも
文字列として $str .= $_;
ってやったほうが良いでしょう。
0154nobodyさん03/07/27 21:00ID:???
>>150
読んでなかった。ごめんにぇ。
0155nobodyさん03/07/27 21:35ID:???
>>154は引き篭もり板のコテハン「chan」か??
0156(*゚p゚)Chan ◆ClChang/Go 03/07/27 22:01ID:???
>>155
(*゚p゚)σ違うにゃりよ!!!
              ε=ε=ε=┌(*゚p゚)ノ サササッ
0157nobodyさん03/07/27 22:11ID:???
(´-`).。oO(どこにもバカコテっているもんだなぁ。。。)
0158nobodyさん03/07/27 22:14ID:???
コテハンはデフォルトでバカ。バカじゃないコテのほうが珍しい。
0159nobodyさん03/07/27 22:16ID:???
アクセスログをopen(FH,">>log.dat")で書き込みして生ログがどんどんかさばってく
スクリプトなのですが、どのへんまでたまったら古いログを消していくべきか
こまっています。

たとえば1MBのログファイルを開け閉めするのと10KBのログファイルを開け閉めするので
処理時間に差が出たりするのでしょうか?
0160nobodyさん03/07/27 22:41ID:???
>>159
>たとえば1MBのログファイルを開け閉めするのと10KBのログファイルを開け閉めするので
>処理時間に差が出たりするのでしょうか?
聞く前に試せよ。その試した結果に疑問があるなら質問しに来い。
0161nobodyさん03/07/27 22:42ID:???
>>159
あるんじゃないの?

何のアクセスログか知らないけれど、
ログを切る方法なんていろいろあるでしょ。

apacheのログ?
rotatelogs。。
logrotate。。。
あるいはシェルとか。
0162nobodyさん03/07/27 22:48ID:???
>>159
アペンドなら有意な差(特に1Mと10Kなら)はないと思う。実測した事ないので>>160が言ってるように
測定して報告してくれ。
0163nobodyさん03/07/27 22:57ID:???
>>161
いえ、apacheのじゃなくてよくある画像を用いたアクセスログです。
あくまで一般的な知識としてどうなのか、と思って訊いてみたんですが。
測定する方法を考えて出なおしてきます。
0164nobodyさん03/07/28 00:32ID:???
効率が気になる奴は自分でプロファイリングでもしてみろっつの。
DProfとかあんだろ。
0165nobodyさん03/07/28 00:39ID:???
>>163
use Benchmark;
0166nobodyさん03/07/28 01:03ID:???
なるほ。
016715903/07/28 04:46ID:???
やってみた。
空のファイルに対してopen(FH,">>$file")でlocaltimeを書き込んでいくループを
やらせてみたら、ファイルサイズが100KBだろうか1MBだろうが10MBになろうが
処理のスピードは変化無しでした。
まあ考えてみたら>>で書き込むのってファイルを開いてポインタを末尾に移動して
書き込むだけだから、そのファイルが小さかろうが大きかろうが関係無いっぽいけど。

ちなみに同じことを毎回行を配列化→pushで追加→>で新規書き込みっていう
ループでやってみたら、当然処理はだんだん遅くなりました。

16[4-5]のモジュールは使い方よくわかりませんでした。
0168nobodyさん03/07/28 06:36ID:+imB0DDx
教えてください。

サーバー上に掲示板のログが大量にあります。
これらを小さくまとめる&転送速度を上げるために、gzipで圧縮して閲覧可能にしたいと思っています。

gzipの圧縮は1度行えばいいので、Windows上かシェルで行い、サーバー上に置いておくことになりますが、
そのファイル名が、$FORM{url} だとすれば、

print "Content-type: text/html;charset=Shift_JIS\n";
unless($ENV{'HTTP_ACCEPT_ENCODING'} =~ /gzip/){&error($FORM{url}); exit; }
if($ENV{'HTTP_ACCEPT_ENCODING'} =~ /x-gzip/){ print "Content-encoding: x-gzip\n\n"; }
elsif ($ENV{'HTTP_ACCEPT_ENCODING'} =~ /gzip/){ print "Content-encoding: gzip\n\n"; }

if (!open(GURL,"<$FORM{url}")){ &error(1); exit; }
binmode GURL;
@gzipdata = <GURL>;
close(GURL);

print @gzipdata;
exit;
#エラーの場合はURLをリンクで示してダウンロードしてローカルで解凍してもらうよう表示する。

こうなるのかと、とりあえず書いてはみたものの、一度メモりに読むのは避けられないのか、
バイナリ扱うPerl書いたことないからこれでいいのか。

あるいはもっと効率的な方法をご存じの方は教えてください。
0169nobodyさん03/07/28 11:36ID:???
下のようにファイルの内容を処理しているのですが、一行ずつ処理する場合
後ろから処理するということはできないでしょうか?

while( <FILE> ) { 処理 }

配列などに入れてしまえばできるのですが、メモリとしてはこちらの方がよいと
思いまして、どうかよろしくお願い致します。
0170nobodyさん03/07/28 11:44ID:???
>169
逆順は難しいと思われ。
一行のバイト数が固定なら色々とやりようもあるだろうが。
可変行の場合、俺はやり方を知らない。

配列でやるんだったら配列の入れ方を工夫するといいかも。
@data = <FILE>;
@data = reverse(@data);
とやるよりも
@data = ();
while(<FILE>){unshift(@data);}
とした方がいいかもしれない。
0171nobodyさん03/07/28 11:45ID:???
>170 =~ s/可変行の場合/一行のバイト数が可変の場合/;
0172nobodyさん03/07/28 12:04ID:???
>>168
試してないけど。

binmode STDOUT;
my $CRLF = "\x0d\x0a";
my $encoding = $ENV{'HTTP_ACCEPT_ENCODING'};

print 'Content-Type: text/html; charset=Shift_JIS', $CRLF;

$encoding =~ /gzip/ or &error($FORM{url}, exit;
open GURL, '<' . $FORM{url} or &error(1), exit;

if ($encoding =~ /x-gzip/) { print 'Content-Encoding: x-gzip', $CRLF }
elsif ($encoding =~ /gzip/) { print 'Content-Encoding: gzip', $CRLF }

print $CRLF;
print while read GURL $_, 1024; # LENGTH は適宜調整
close GURL;

>>169
http://www.din.or.jp/~ohzaki/perl.htm#File_Reverse
0173nobodyさん03/07/28 12:09ID:???
>>169
File::ReadBackwards
0174nobodyさん03/07/28 12:16ID:???
>>168
Content Negotiationに任せればいいのでは?
0175nobodyさん03/07/28 13:21ID:ZypqctSD
変数はmyで局所化するのが基本みたいなんでそうしていますが、
例えば同じ変数をどこのサブルーチンで使いたい場合はどうするんでしょうか。
いちいち変数の受け渡しをしないといけないんでしょうか。
0176nobodyさん03/07/28 13:45ID:???
>>175
局所化しなきゃいい。
0177nobodyさん03/07/28 13:47ID:???
>>168
174が言ってるように、ファイル名に.gz追加
logfile1.html.gz
HTTP_ACCEPT_ENCODING見てサーバがファイルを選んでくれる。
0178nobodyさん03/07/28 13:49ID:mZs5gojb
>>175
our。バージョン古くて使えなければuse vars。
0179nobodyさん03/07/28 13:52ID:???
>>175
妙な静的変数

{
my $static;
sub hoge {
}
sub hogehoge {
}
sub hagehage {
}
}
0180nobodyさん03/07/28 14:33ID:MPvwsvte
画像掲示板をつくっています。参照ボタンでローカルパソコン内の画像を選んだあと、
確認ボタンでその画像がブラウザで確認出来るようにしたいのですが、
良い方法ないでしょうか?
0181nobodyさん03/07/28 14:34ID:???
>>180
帰れ。
0182nobodyさん03/07/28 14:41ID:???
>>167
> 16[4-5]のモジュールは使い方よくわかりませんでした。

使えるようになると便利だぞ。
面倒かもしれんけど、ぐぐってみるなりして使いこなせ。


>>180
送信する前にプレビューってことか?
JavaScriptでフォームからファイルパス取って、IMGに埋め込むとか。
できるかわからんけど。
とりあえずスレ違いなので詳細はそれ系スレで。
0183nobody03/07/28 21:25ID:0jEUdWDa
ス…スマン。大学のperlの課題で四苦八苦している者です。
「じゃんけん」ができるプログラムを作りたいんだけど
何かいい方法ありますか?
当方かなり初心者なんで
print"〜";#って文字を出力することしかできないんですけど。
えーと質問の意味がわからなかったらスルーしてもらってもかまいません。
0184あぼーんNGNG
あぼーん
0185nobodyさん03/07/28 21:53ID:???
>183
まずフローチャートを書け。
それ以降は大学で聞け。
0186nobodyさん03/07/28 21:58ID:???
>>183
宿題は自分でやろうね。
0187nobodyさん03/07/28 22:03ID:???
print "じゃんけん\n";
sleep(1);
print "ぽん\n";
0188あぼーんNGNG
あぼーん
0189nobodyさん03/07/28 22:10ID:TipKdKzd
じゃんけん・・・
ランダムに3つの中から選ぶプログラムを作って
自分で入力した文字と比較。
結果を出力。でいいんじゃない?
0190あぼーんNGNG
あぼーん
0191nobodyさん03/07/28 22:25ID:???
>>183

print "じゃんけん(1=ぐー、2=ぱー、3=ちょき)\n";
<>;chop;
$a = int rand(3)+1;
$hoge = (($a == 1 && $_ == 2) || ($a == 2 && $_ == 3) || ($a == 3 && $_ == 1)) ? '勝ち' : '負け';
print $hoge,"\n";

# お粗末
0192nobodyさん03/07/28 22:47ID:???
183は課題がでるたびにここで聞くのかね。
0193nobodyさん03/07/28 22:53ID:???
print "じゃんけん(1=ぐー、2=ぱー、3=ちょき)\n";
<>;
print ('勝ち', '負け')[int rand 2];
0194nobodyさん03/07/28 23:08ID:???
>>193

   /⌒ヽ
  / ´_ゝ`)時間的に、ここ笑わないといけないので、笑いますよ・・・
  |    /
  | /| |
  // | |
 U  .U
019518303/07/28 23:46ID:xYLAJnZK
課題今日中にメールで提出ということだったんで…出しました。
みなさんいろいろ案出していただいてありがとうございます。
結局自分の力不足で課題内容変えちゃいましたけど。
(みなさんの案は今後参考にさせてもらいます)
>192
今日始めてここに来たんですけど
まぁ課題が出るたびにここで聞くのと同じような根性の持ち主です。

とにかく…評価はCにケテーイぽ(つД`)
0196あぼーんNGNG
あぼーん
0197nobodyさん03/07/28 23:49ID:???
>>183 っていうか、おまえ。答え丸写しじゃねぇかw
0198nobodyさん03/07/28 23:56ID:???
あいこが出ないコードを提出。-10点
0199あぼーんNGNG
あぼーん
020018303/07/29 00:01ID:BcdoPCM8
>197
いやしてないし。むしろじゃんけんにしなかったし。
ウザイのでそろそろ逝きます。
0201nobodyさん03/07/29 00:03ID:???
まあ、はじめから丸写しするつもりで聞いたんだろう。
自分の期待する答えがなかったからしなかった(というかできなかった)だけで。
0202nobodyさん03/07/29 00:25ID:???
そういうやつのためにも時々ウソを教えないとね
試したらわかる程度に軽いやつで
0203nobodyさん03/07/29 01:49ID:???
それにしても 183 よ。そんな事を2ちゃんねるで聞くのもどうかと思うぞw
020416803/07/29 07:41ID:???
>>174
ありがとうございました。

Content Negotiationというのがあるとは全く知らず、そのまま表示できたのでびっくりです。
板違いでしたね(汗)
全部圧縮して、リンク先のアドレス変えるだけで問題はすべて解決しました。

大変感謝しております。
0205nobodyさん03/07/29 08:56ID:pmxt/hz7
crontabで、AM6:00,AM7:00に1回起動設定しているとして、
cgiの中でlocaltimeで、6:00と7:00で処理を分けているんですけど、
crontabの時計とlocaltimeの時計は完全に一致しているんでしょうか?
スクリプトの中で6:00丁度だったらA、7:00丁度だったらBとやっても
crontabが起動した時間が5:58とかだったらAの処理が行われないと思うんです。
0206nobodyさん03/07/29 10:14ID:???
cgiがperlで書かれているとすれば。
perldoc を調べなさい。
それから
man crontab。
0207nobodyさん03/07/29 10:15ID:???
ちがう。
crontabはcrontableのことだ。
要するにcronの設定ファイル(といっていいかどうかわからんが)

man cron
をすべき。
0208nobodyさん03/07/29 10:21ID:???
ついでにいうと、localtimeじゃなくてtimeだよな。
0209nobodyさん03/07/29 10:39ID:???
>>205
6:00丁度に起動されたとしてもlocaltimeとるまでにタイムラグがある。
ちょっと考えればわかりそうなもんだが。
0210nobodyさん03/07/29 10:52ID:???
man cron ってヤラスィ〜響き

(*´Д`*) マンコロン・・・
0211あぼーんNGNG
あぼーん
0212nobodyさん03/07/29 11:44ID:pmxt/hz7
man cronってなんざんすか?
0213nobodyさん03/07/29 11:47ID:MFa+8P58
一定時間ごとにある処理をさせますが、特定のキー入力で抜けます。
<STDIN>; ではうまくいかないので下のコードのようにしましたが、
2つ目のwhileを無駄に回さなくてもいいようにする方法はありますかね?
今のところsleepを入れるくらいしか思いつかないです。

sub {
  my $sig = 0;
  local $SIG{INT} = sub {$sig = 1;};
  while (1) {
    # ここに$interval(分)ごとにする処理
    while (time() % ($interval * 60)) {
      sleep (1);
      return 1 if($sig);
    }
  }
}
0214あぼーんNGNG
あぼーん
0215nobodyさん03/07/29 12:00ID:???
>>213
1 TTYをnon-canonicalモードにする。
プラットフォーム依存。モジュールあるかも。
2 特定のキーでシグナル発生させる。
0216nobodyさん03/07/29 12:03ID:???
>>213
getc じゃ駄目なの?
0217nobodyさん03/07/29 15:52ID:???
今 ttp://x68000.startshop.co.jp/~68user/net/http-2.html
を参考にhttpクライアントを作ってみたんですが
どうも404が返ってくるところが多くて不思議なのですが
どういうことなのでしょう?
例えば参考にした上のページは見れるんですが
自分のISPのページは
Http://host/~user/index.html でリクエストすると404で
Http://host/~user/ なら大丈夫なんです。
(勿論ブラウザなら両方OKです。)

ソースへ
print SOCKET "Host:$host:$port\r\n";
を追加したら大抵取得できる様になったんですが
それでも100%でないので納得できないのです。
何が不足しているのでしょうか?
サッパリ意味が解らないのでご教授お願いします。
0218nobodyさん03/07/29 16:04ID:???
>>217
バーチャルホスト
021921703/07/29 16:39ID:???
>>218
バーチャルホストへは
print SOCKET "Host:$host:$port\r\n";
で対応できているんですよね?

何だか原因はスペルミスだけだった気がしてきました。
0220nobodyさん03/07/29 16:53ID:???
>>218 (゚Д゚)ハァ?

>>217 サーバーの DirectoryIndex (クライアントがディレクトリをリクエストしたときに調べるリソースのリスト)確認しろ。
0221nobodyさん03/07/29 17:35ID:???
>>220 (゚Д゚)ハァ?
>(勿論ブラウザなら両方OKです。)
0222nobodyさん03/07/29 19:38ID:71pkcqEp
>>220
(゚Д゚ )ハァ?
それで返ってくるのは403だろ。氏ねや
0223あぼーんNGNG
あぼーん
0224nobodyさん03/07/29 19:55ID:???
connect の後に SELECT してるけど、代わりに autoflush SOCKET (1); は?
0225nobodyさん03/07/29 21:36ID:???
>>213
alarm使って、キー待ちにしたらどう?
time値の0秒ジャストで動かせないけど。

local $SIG{ALRM} = sub { die 'timeout' };

...
my $c = &keywait(1);
...

sub keywait
{
my $interval = shift;

eval{
alarm($interval*60);
<>;
alarm(0);
};
if ($@){
alarm(0);
($@ =~ /timeout/) or die;
return(0);
}

return(1);
}
0226nobodyさん03/07/29 21:40ID:???
>>217
プロトコルをHTTP/1.1にしたら?
0227nobodyさん03/07/29 23:46ID:Y5f15xmJ
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
#$buffer = $ENV{'QUERY_STRING'};

@pairs = split(/&/, $buffer);
foreach (@pairs) {
($key, $val) = split(/=/);
$in{$key} = $val;
}

ここまでやった後で連想配列の中身を見る方法を教えてください。
どんなkeyが入ってるか知りたいのです。それによって処理を分岐するので。
初歩的な質問ですみません。
0228nobodyさん03/07/29 23:48ID:???
>>227
そのままだけど、keys。
0229nobodyさん03/07/29 23:48ID:???
keys
0230nobodyさん03/07/29 23:48ID:???
>>227
foreach $key ( sort( keys %ENV ) ) {
print "$key = $ENV{$key}\n";
}
0231nobodyさん03/07/29 23:49ID:???
>>230
ENV???
0232nobodyさん03/07/29 23:56ID:???
>>227
print map { "$_ : $in{$_}\n" } keys %in;
■ このスレッドは過去ログ倉庫に格納されています